Coverage report: /development/source/library/org/datagraph/spocq-shard/src/algebra/operators/dydra-operators.lisp
| Kind | Covered | All | % |
| expression | 34 | 1130 | 3.0 |
| branch | 0 | 66 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-
3
(in-package :org.datagraph.spocq.implementation)
5
(:documentation "This file defines the GIS extension operators for the 'org.datagraph.spocq' RDF engine."
8
"Copyright 2010 [james anderson](mailto:james.anderson@setf.de) All Rights Reserved.")
11
"The file defines the dydra extension operators for SPOCQ. The initial complement emulates the
12
Virtuose SPARQL extensions[1] to support the good relations PHP API[2].
15
[1]: http://docs.openlinksw.com:80/virtuoso/functions.html
16
[2]: http://code.google.com/p/gr4php/source/browse/gr4php_template.php
22
(defun |dydra|:|contains| (string substring)
23
(when (search substring string)))
25
(defun |dydra|:|round| (term)
26
(spocq.e::round term))
28
(defun |dydra|:|st_distance| (point-1 point-2)
29
(flet ((square (x) (* x x)))
30
(sqrt (+ (square (- (point-x point-1) (point-x point-2)))
31
(square (- (point-y point-1) (point-y point-2)))))))
33
(defun |dydra|:|st_point| (latitude longitude)
34
(make-point :x latitude :y longitude))
36
(defun |dydra|:|st_x| (point)
39
(defun |dydra|:|st_y| (point)
44
(defgeneric |dydra|:|format| (value specification &key zone)
45
(:method ((value spocq:date-time) (specification string) &key (zone 0))
46
(with-output-to-string (stream)
47
(multiple-value-call #'format-time-values
49
(decode-temporal value zone))))
50
(:method ((value spocq:date) (specification string) &key (zone 0))
51
(with-output-to-string (stream)
52
(multiple-value-call #'format-time-values
54
(decode-temporal value zone))))
55
(:method ((value integer) (specification string) &key (zone 0))
56
(with-output-to-string (stream)
57
(multiple-value-call #'format-time-values
59
(decode-temporal value zone))))
60
(:method ((value spocq:duration) (specification string) &key (zone 0))
61
(with-output-to-string (stream)
62
(multiple-value-call #'format-time-values
64
(decode-temporal value zone))))
65
(:method ((value spocq:time) (specification string) &key (zone 0))
66
(with-output-to-string (stream)
67
(multiple-value-call #'format-time-values
69
(decode-temporal value zone)))))
70
;;; (|dydra|:|format| (spocq.e:now) "%Y-%m-%dT%H:%i:%s")
71
;;; (|dydra|:|format| (spocq.e:now) "%Y-%m-%dT%H:%i:%s" 3)
74
(defun format-time-values (stream specification fraction second minute hour day month year)
76
(length (length specification))
77
(day-of-the-week nil))
78
(flet ((local-day-of-the-week ()
81
(multiple-value-bind (second minute hour day month year dotw)
82
(decode-universal-time (encode-universal-time second minute hour day month year 0))
83
(declare (ignore second minute hour day month year))
85
(loop (when (>= index length) (return))
86
(let ((char (char specification index)))
89
(when (< (incf index) length)
90
(case (char specification index)
91
(#\a ;Abbreviated weekday name
92
(write-string (subseq (date:day-in-week-name (local-day-of-the-week)) 0 3) stream))
93
(#\b ;Abbreviated month name
94
(write-string (subseq (date:month-name month) 0 3) stream))
97
(#\D ;Day of month with English suffix
98
(format stream "~:r" month))
99
(#\d ;Day of month, numeric (00-31)
100
(format stream "~2,'0d" day))
101
(#\e ;Day of month, numeric (0-31)
104
(princ (if fraction (round fraction .000001) 0) stream))
106
(format stream "~2,'0d" hour))
108
(let ((mod-12 (mod hour 12)))
109
(format stream "~2,'0d" (if (zerop mod-12) 12 mod-12))))
111
(let ((mod-12 (mod hour 12)))
112
(format stream "~2,'0d" (if (zerop mod-12) 12 mod-12))))
113
(#\i ;Minutes, numeric (00-59)
114
(format stream "~2,'0d" minute))
115
(#\j ;Day of year (001-366)
116
(let ((doy (date:day-and-month-to-day-in-year day month (date:leap-p year))))
117
(format stream "~3,'0d" doy)))
119
(format stream "~2,'0d" hour))
121
(let ((mod-12 (mod hour 12)))
122
(princ (if (zerop mod-12) 12 mod-12) stream)))
124
(write-string (date:month-name month) stream))
125
(#\m ;Month, numeric (00-12)
126
(format stream "~2,'0d" month)
129
(write-string (if (>= hour 12) "PM" "AM") stream))
130
(#\r ;Time, 12-hour (hh:mm:ss AM or PM)
131
(let ((mod-12 (mod hour 12)))
132
(format stream "~2,'0d:~2,'0d:~2,'0d" (if (zerop mod-12) 12 mod-12) minute second)))
133
(#\S ;Seconds (00-59)
134
(format stream "~2,'0d" second))
135
(#\s ;Seconds (00-59)
136
(format stream "~2,'0d" second))
137
(#\T ;Time, 24-hour (hh:mm:ss)
138
(format stream "~2,'0d:~2,'0d:~2,'0d" hour minute second))
139
(#\U ;Week (00-53) where Sunday is the first day of week
140
(format stream "~2,'0d" (date::day-and-month-any-year-to-week-in-year day month year :start-of-week :sunday)))
141
(#\u ;Week (00-53) where Monday is the first day of week
142
(format stream "~2,'0d" (date::day-and-month-any-year-to-week-in-year day month year)))
143
(#\V ;Week (01-53) where Sunday is the first day of week, used with %X
144
(format stream "~2,'0d" (1+ (date::day-and-month-any-year-to-week-in-year day month year :start-of-week :sunday))))
145
(#\v ;Week (01-53) where Monday is the first day of week, used with %x
146
(format stream "~2,'0d" (1+ (date::day-and-month-any-year-to-week-in-year day month year))))
148
(write-string (date:day-in-week-name (mod (1+ (local-day-of-the-week)) 7)) stream))
149
(#\w ;Day of the week (0=Sunday, 6=Saturday)
150
(princ (mod (1+ (local-day-of-the-week)) 7) stream))
151
(#\X ;Year of the week where Sunday is the first day of week, four digits, used with %V
152
(format stream "~4,'0d" year)) ; ??
153
(#\x ;Year of the week where Monday is the first day of week, four digits, used with %v
154
(format stream "~4,'0d" year)) ; ??
155
(#\Y ;Year, four digits
156
(format stream "~4,'0d" year))
157
(#\y ;Year, two digits
158
(format stream "~2,'0d" (mod year 100)))))
161
(write-char char stream)
164
(defun date::day-and-month-any-year-to-week-in-year (day month year &key (start-of-week :monday))
165
(multiple-value-bind (s m h d mo y ysdow)
166
(decode-universal-time (encode-universal-time 1 1 1 1 1 year 0) 0)
167
(declare (ignore s m h d mo y))
168
(let* ((doy (date:day-and-month-to-day-in-year day month (date:leap-p year)))
169
(week (floor (+ doy ysdow (ecase start-of-week (:monday -1) (:sunday 0))) 7)))
170
(values week ysdow doy))))
173
;;; (format-time-values t "%Y-%m-%dT%H" nil 1 1 1 1 5 2006 0 nil 0)
174
;;; (get-decoded-time)
175
;;; (loop for day from 1 to 15 collect (list day (date::day-and-month-any-year-to-week-in-year day 1 2013)))
176
;;; (loop for day from 1 to 15 collect (list day (date::day-and-month-any-year-to-week-in-year day 1 2013 :start-of-week :sunday)))
177
;;; (|dydra|:|format| (spocq.e:now) "%Y-%m-%d")
180
(defgeneric |dydra|:|timestamp-date-time| (timestamp)
181
(:method ((timestamp integer))
182
(if (plusp timestamp)
183
(timeline-location-date-time timestamp)
185
(:method ((timestamp t))
186
(invalid-argument-type |dydra|:|timestamp-date-time| timestamp |xsd|:|nonNegativeInteger|)))
188
(defgeneric |dydra|:|date-time-timestamp| (timestamp)
189
(:method ((date-time spocq:date-time))
190
(date-time-timeline-location date-time))
191
(:method ((date-time t))
192
(invalid-argument-type |dydra|:|date-time-timestamp| date-time |xsd|:|dateTime|)))
196
(defun |dydra|:|iri-authority| (iri)
197
(puri:uri-authority (puri:uri iri)))
199
(defun |dydra|:|iri-fragment| (iri)
200
(puri:uri-fragment (puri:uri iri)))
202
(defun |dydra|:|iri-host| (iri)
203
(puri:uri-host (puri:uri iri)))
205
(defun |dydra|:|iri-path| (iri)
206
(puri:uri-path (puri:uri iri)))
208
(defun |dydra|:|iri-password| (iri)
209
(puri:uri-password (puri:uri iri)))
211
(defun |dydra|:|iri-port| (iri)
212
(puri:uri-port (puri:uri iri)))
214
(defun |dydra|:|iri-query| (iri)
215
(puri:uri-query (puri:uri iri)))
217
(defun |dydra|:|iri-scheme| (iri)
218
(let ((scheme (puri:uri-scheme (puri:uri iri))))
219
(if scheme (string scheme) "")))
221
(defun |dydra|:|iri-user| (iri)
222
(puri:uri-user (puri:uri iri)))
224
(defun |dydra|:|iri-userinfo| (iri)
225
(puri:uri-userinfo (puri:uri iri)))
228
(let ((iri (spocq.e:iri "http://user:pw@host.net:0001/path1/path2/object.ext?parm1=1&parm2=2#fragment")))
229
(loop for function being each external-symbol in "http://dydra.com#"
230
for name = (string function)
231
when (and (> (length name) 4) (string-equal "iri-" name :end2 4))
232
collect (list function (funcall function iri))))
234
(defmethod |dydra|:|urn-uuid-string| ((uuid spocq:uuid))
235
(subseq (spocq::uuid-lexical-form uuid) 9))
237
;;; (|dydra|:|urn-uuid-string| (intern-iri (make-v1-uuid-string)))
240
* (run-test-query "select (<http://dydra.com#format>(?date, '%Y-%m-%d') as ?ts)
242
where { ?s <http://example.org/date> ?date }"
243
:repository-id (lookup-repository-id :repository-name "functions-day-zulu" :account-name "jhacker"))
245
(("2010-06-21" "2010-06-21T11:28:01Z") ("2010-12-21" "2010-12-21T23:38:02Z")
246
("2008-06-20" "2008-06-20T23:59:00Z") ("2011-02-01" "2011-02-01T01:02:03Z")
247
("2011-01-01" "2011-01-01T03:02:03Z") ("2011-01-01" "2011-01-01T01:02:03Z")
248
("2010-12-31" "2010-12-31T23:02:03Z") ("2012-01-01" "2012-01-01T01:24:25Z")
249
("2011-12-31" "2011-12-31T23:24:25Z") ("2011-12-31" "2011-12-31T21:24:25Z"))
254
select ?ts (count(?date) as ?count) {
255
select (<http://dydra.com#format>(?date, '%Y-%m-%d', +4) as ?ts) ?date
256
where { ?s <http://example.org/date> ?date }
259
:repository-id (lookup-repository-id :repository-name "functions-day-zulu" :account-name "jhacker"))
260
(("2010-06-21" 1) ("2010-12-21" 1) ("2008-06-20" 1) ("2011-01-31" 1)
261
("2010-12-31" 3) ("2011-12-31" 3))
266
(:documentation "Reification"
267
"The identifier for a statement is a tri-part urn, of which each component is the respective
268
term sha-1. It has meaning for only those combinations for which the terms exist in the store and is
269
intended itself to be interned. That is, if the identifer has not been interned, the return values from
270
the component accessors will all be unbound indicators."
273
(defun |dydra|::|statement-urn| (subject predicate object)
274
(unless (or (spocq:iri-p subject) (spocq:blank-node-p subject))
275
(spocq.e:argument-type-error :datum subject
276
:operator '|dydra|::|statement-urn|
277
:expected-type '(or spocq:iri spocq:blank-node)))
278
(unless (spocq:iri-p predicate)
279
(spocq.e:argument-type-error :datum predicate
280
:operator '|dydra|::|statement-urn|
281
:expected-type 'spocq:iri))
282
(let ((subject-id (rlmdb:value-term-number subject :if-does-not-exist nil))
283
(predicate-id (rlmdb:value-term-number predicate :if-does-not-exist nil))
284
(object-id (rlmdb:value-term-number object :if-does-not-exist nil)))
285
(if (and subject-id predicate-id object-id)
286
(intern-iri (rdf-statement-urn-string subject-id predicate-id object-id))
287
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-subject|)))))
289
(defun rdf-statement-urn-string (subject-id predicate-id object-id)
290
"Given three term numbers, compute the respective id urn string.
291
This permits constructs for statements which do not exist in the store, so long as the terms do"
292
(dydra-ndk::statement-urn-string subject-id predicate-id object-id))
295
(defun |dydra|:|statement-subject| (id-urn)
296
"Given an urn identifier for a known statement, return the component."
299
(let ((statement-id-term-number (rlmdb:value-term-number id-urn :if-does-not-exist nil)))
300
(if statement-id-term-number
301
;; the terms must have been interned
302
(rlmdb:term-number-value (dydra-ndk::statement-subject-id statement-id-term-number))
303
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-subject|)))))
304
(spocq:unbound-variable
305
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-subject|)))
307
(spocq.e:argument-type-error :datum id-urn
308
:operator '|dydra|:|statement-subject|
309
:expected-type 'spocq:iri))))
311
(define-compiler-macro |dydra|:|statement-subject| (&whole form id-urn &environment env)
312
(let ((expansion (macroexpand-1 id-urn env)))
313
(if (field-object-aref-p expansion)
314
`(let ((.term-number (aref ,@(field-object-aref-aref expansion))))
315
(if (eql .term-number +null-term+)
316
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-subject|))
317
(rlmdb:term-number-value (dydra-ndk::statement-subject-id .term-number))))
321
(defun |dydra|:|statement-predicate| (id-urn)
322
"Given an urn identifier for a known statement, return the component."
325
(let ((statement-id-term-number (rlmdb:value-term-number id-urn :if-does-not-exist nil)))
326
(if statement-id-term-number
327
;; the terms must have been interned
328
(rlmdb:term-number-value (dydra-ndk::statement-predicate-id statement-id-term-number))
329
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-predicate|)))))
330
(spocq:unbound-variable
331
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-predicate|)))
333
(spocq.e:argument-type-error :datum id-urn
334
:operator '|dydra|:|statement-predicate|
335
:expected-type 'spocq:iri))))
337
(define-compiler-macro |dydra|:|statement-predicate| (&whole form id-urn &environment env)
338
(let ((expansion (macroexpand-1 id-urn env)))
339
(if (field-object-aref-p expansion)
340
`(let ((.term-number (aref ,@(field-object-aref-aref expansion))))
341
(if (eql .term-number +null-term+)
342
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-predicate|))
343
(rlmdb:term-number-value (dydra-ndk::statement-predicate-id .term-number))))
347
(defun |dydra|:|statement-object| (id-urn)
348
"Given an urn identifier for a known statement, return the component."
351
(let ((statement-id-term-number (rlmdb:value-term-number id-urn :if-does-not-exist nil)))
352
(if statement-id-term-number
353
;; the terms must have been interned
354
(rlmdb:term-number-value (dydra-ndk::statement-object-id statement-id-term-number))
355
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-object|)))))
356
(spocq:unbound-variable
357
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-object|)))
359
(spocq.e:argument-type-error :datum id-urn
360
:operator '|dydra|:|statement-object|
361
:expected-type 'spocq:iri))))
362
(define-compiler-macro |dydra|:|statement-object| (&whole form id-urn &environment env)
363
(let ((expansion (macroexpand-1 id-urn env)))
364
(if (field-object-aref-p expansion)
365
`(let ((.term-number (aref ,@(field-object-aref-aref expansion))))
366
(if (eql .term-number +null-term+)
367
(load-time-value (spocq:make-unbound-variable '|dydra|:|statement-object|))
368
(rlmdb:term-number-value (dydra-ndk::statement-object-id .term-number))))
372
;;; query state introspection
374
(defun |dydra|:|account-name| ()
376
(let ((account (or (task-account *task*)
377
(repository-account (task-repository *task*)))))
378
(when account (account-name account))))
379
(load-time-value (spocq:make-unbound-variable '|dydra|:|account-name|))))
381
(defun |dydra|:|agent-id| ()
382
"Return the agent id respective the current task or, if none is available, an
384
(or (task-agent-id *task*)
385
(load-time-value (spocq:make-unbound-variable '|dydra|:|agent-id|))))
387
(defun |dydra|:|agent-location| ()
388
"Return the agent location respective the current task or, if none is available, an
390
(or (task-agent-location *task*)
391
(load-time-value (spocq:make-unbound-variable '|dydra|:|agent-location|))))
393
(defun |dydra|:|client-request-id| () (|dydra|:|user-tag|))
396
;;; !!! nb. there is no |dydra|:|event| operator
397
;;; an event binding is a side-effect of statement scanning for indices which include
398
;;; an event designator in the key
400
(defgeneric |dydra|:|event-ordinal| (event-designator)
401
(:documentation "Return the equivalent event ordinal for the current repository.
402
Given an ordinal, return it directly.")
403
(:method ((designator integer))
405
(:method ((designator t))
406
(or (when *repository*
407
(let ((record (rlmdb:find-revision-record *repository* designator)))
409
(rlmdb:revision-record-ordinal record))))
410
(load-time-value (spocq:make-unbound-variable '|dydra|:|event-ordinal|)))))
412
(defgeneric |dydra|:|event-timestamp| (event-designator)
413
(:documentation "Return the equivalent date-time timestamp for the current repository.
414
Given a timestamp. return it directly")
415
(:method ((designator spocq:date-time))
417
(:method ((designator t))
418
(or (when *repository*
419
(let ((record (rlmdb:find-revision-record *repository* designator)))
421
(timeline-location-date-time (rlmdb:revision-record-timestamp record)))))
422
(load-time-value (spocq:make-unbound-variable '|dydra|:|event-timestamp|)))))
424
(defgeneric |dydra|:|event-uuid| (event-designator)
425
(:documentation "Return the equivalent uuid string for the current repository.
426
Given an uuid. return it directly")
427
(:method ((designator string))
428
(or (when *repository*
429
(let ((record (rlmdb:find-revision-record *repository* designator)))
431
(rlmdb:revision-record-uuid record))))
432
(load-time-value (spocq:make-unbound-variable '|dydra|:|event-uuid|)))))
435
(defun |dydra|:|query-uri| ()
436
"This function returns the IRI of the current query."
437
(or (when *task* (task-uuid *task*))
438
(load-time-value (spocq:make-unbound-variable '|dydra|:|query-uri|))))
440
(defun |dydra|:|repository-name| ()
441
"Return the name of the current query's target repository"
442
(or (when *task* (repository-name (task-repository *task*)))
443
(load-time-value (spocq:make-unbound-variable '|dydra|:|repository-name|))))
445
;;; the now returns the incorrect uri - therepository rahter than with the revision
446
(defun |dydra|:|repository-revision-url| ()
447
"Return the URL of the current query's repository's revision"
448
(or (when *task* (repository-revision-uri (task-transaction *task*)))
449
(load-time-value (spocq:make-unbound-variable '|dydra|:|repository-revision-url|))))
451
(defun |dydra|:|repository-revision-count| ()
452
"Return the number of revisions for a revisioned repository.
453
If unrevisioned, return 0 - even though there is always one revision."
455
(let ((repository (task-repository *task*)))
456
(if (repository-is-revisioned repository)
457
(length (repository-list-revision-ids repository))
459
(load-time-value (spocq:make-unbound-variable '|dydra|:|repository-revision-url|))))
461
(defun |dydra|:|repository-url| ()
462
"Returns the URL of the current query's repository"
463
(or (when *task* (repository-uri (task-repository *task*)))
464
(load-time-value (spocq:make-unbound-variable '|dydra|:|repository-url|))))
466
(defun |dydra|:|request-id| () (|dydra|:|query-uri|))
468
(defun |dydra|:|resolve-revision| (revision-designator &optional silent)
469
"Given a revision designator, resolve it to the respective uuid and return the value"
470
(unless (stringp revision-designator)
471
(spocq.e:argument-type-error :datum revision-designator
472
:operator '|dydra|:|resolve-revision|
473
:expected-type |xsd|:|string|))
474
(or (when *repository* (let* ((if-does-not-exist (if (ebv silent) nil :error))
475
(id (resolve-repository-revision-id *repository*
476
:revision revision-designator
477
:if-does-not-exist if-does-not-exist)))
478
(when id (intern-uuid id))))
479
(load-time-value (spocq:make-unbound-variable '|dydra|:|resolve-revision|))))
481
;;; revision-based operators are of two kinds
482
;;; the first regard properties of the active revision and/or task's transaction
483
;;; (which ought to be the same?)
484
;;; the second relate as well to revision identifiers
485
(defun |dydra|:|revision-parent-uri| ()
486
"This function returns the IRI of the current query's active transactions's parent."
487
(or (when *task* (revision-parent-uri (task-transaction *task*)))
488
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision-parent-uri|))))
490
(defgeneric |dydra|:|revision-predecessor| (revision-designator)
491
(:documentation "Return the revision which precedes that given.")
492
(:method ((revision rlmdb:revision-record))
494
(let ((record (rlmdb:find-revision-record *repository* revision :offset -1
495
:if-does-not-exist nil)))
497
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision-predecessor|))))))
498
(:method ((designator t))
499
(let ((record (|dydra|:|revision| designator)))
501
(rlmdb:revision-record (|dydra|:|revision-predecessor| record))
502
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-predecessor|)))))))
504
(defgeneric |dydra|:|revision-successor| (revision-designator)
505
(:documentation "Return the revision which precedes that given.")
506
(:method ((revision rlmdb:revision-record))
508
(let ((record (rlmdb:find-revision-record *repository* revision :offset -1
509
:if-does-not-exist nil)))
511
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision-successor|))))))
512
(:method ((designator t))
513
(let ((record (|dydra|:|revision| designator)))
515
(rlmdb:revision-record (|dydra|:|revision-successor| record))
516
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-successor|)))))))
518
;;; |dydra|:|revision-end-uri| : see rmdb/repositorystreaming
519
;;; |dydra|:|revision-start-uri| : see rmdb/repositorystreaming
521
(defgeneric |dydra|:|revision| (revision-designator)
522
(:documentation "Return the rlmdb revision record respective the given designator.")
523
(:method ((revision rlmdb:revision-record))
525
(:method ((revision integer))
527
(let ((record (rlmdb:find-revision-record *repository* revision)))
530
(spocq.e:resource-not-found-error :identifier revision)))
531
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision|))))
532
(:method ((revision vector))
534
(let ((record (rlmdb:find-revision-record *repository* revision)))
537
(spocq.e:resource-not-found-error :identifier revision)))
538
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision|))))
539
(:method ((revision repository-revision))
540
(repository-revision-record revision))
541
(:method ((revision null))
542
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision|)))
543
(:method ((revision spocq:unbound-variable))
544
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision|)))
545
(:method ((revision t))
546
(invalid-argument-type |dydra|:|revision| revision |urn:dydra|:|Revision|)))
549
(defgeneric |dydra|:|revision-date-time| (revision)
550
(:documentation "Return the dateTime for the respective revision's commit timestamp")
551
(:method ((revision rlmdb:revision-record))
552
(rlmdb:revision-record-date-time revision))
553
(:method ((designator t))
554
(let ((record (|dydra|:|revision| designator)))
556
(rlmdb:revision-record (rlmdb:revision-record-date-time record))
557
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-date-time|)))))))
560
(defgeneric |dydra|:|revision-ordinal| (revision)
561
(:documentation "Return the revision's internal revision ordinal")
562
(:method ((revision rlmdb:revision-record))
563
(rlmdb:revision-record-ordinal revision))
564
(:method ((designator t))
565
(let ((record (|dydra|:|revision| designator)))
567
(rlmdb:revision-record (rlmdb:revision-record-ordinal record))
568
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-ordinal|)))))))
571
(defgeneric |dydra|:|revision-commit-timestamp| (revision)
572
(:documentation "Return the respective revision's commit unix timestamp")
573
(:method ((revision rlmdb:revision-record))
574
(rlmdb:revision-record-timestamp revision))
575
(:method ((designator t))
576
(let ((record (|dydra|:|revision| designator)))
578
(rlmdb:revision-record (rlmdb:revision-record-timestamp record))
579
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-commit-timestamp|)))))))
582
(defgeneric |dydra|:|revision-begin-timestamp| (revision)
583
(:documentation "Return the respective revision's start unix timestamp")
584
(:method ((revision rlmdb:revision-record))
585
(rlmdb:revision-record-timestamp-begun revision))
586
(:method ((designator t))
587
(let ((record (|dydra|:|revision| designator)))
589
(rlmdb:revision-record (rlmdb:revision-record-timestamp-begun record))
590
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-begin-timestamp|)))))))
593
(defgeneric |dydra|:|revision-uuid| (revision)
594
(:documentation "Return the respective revision's uuid")
595
(:method ((revision rlmdb:revision-record))
596
(rlmdb:revision-record-uuid revision))
597
(:method ((designator t))
598
(let ((record (|dydra|:|revision| designator)))
600
(rlmdb:revision-record (rlmdb:revision-record-uuid record))
601
(t (load-time-value (spocq:make-unbound-variable '|dydra|:|revision-uuid|)))))))
604
;;; concerning the identifier
605
(defgeneric |dydra|:|revision-uuid-node| (uri)
606
(:documentation "Return the node field of the revision uuid")
607
(:method ((uri null))
609
(:method ((uri string))
611
(:method ((uri spocq:uuid))
613
(:method ((uri vector))
615
(:method ((revision t))
616
(|dydra|:|revision-uuid-node| (|dydra|:|revision-uuid| revision))))
618
(defgeneric |dydra|:|revision-uuid-timestamp| (uri)
619
(:documentation "Return the timestamp field of the revision uuid")
620
(:method ((uri null))
622
(:method ((uri string))
623
(v1-uuid-timestamp uri))
624
(:method ((uri spocq:uuid))
625
(v1-uuid-timestamp uri))
626
(:method ((uri vector))
627
(v1-uuid-timestamp uri))
628
(:method ((revision t))
629
(|dydra|:|revision-uuid-timestamp| (|dydra|:|revision-uuid| revision))))
632
;;; the version operators concern the attributes of the current revision or
633
;;; - when in the context of a bgp, the matched statement's revision.
634
;;; this is handled by the continuation in the bgp which accepts matched quads
635
;;; and their respective visibility bounds
637
(defun |dydra|:|version| (&optional (version *version*))
638
"This function returns the revision interval version instance comprising the
639
current start revision and optionally the end revision.
640
If no dynamic binding exists, it constructs a new instance."
643
(spocq:make-revision-interval
644
:start (repository-revision-record *repository*)
645
:end (rlmdb:find-revision-record *repository*
646
(1+ (repository-revision-ordinal *repository*)))))
648
(load-time-value (spocq:make-unbound-variable '|dydra|:|version|)))))
650
(defun |dydra|:|version-end-date-time| (&optional (version (|dydra|:|version|)))
651
"This function returns the IRI of the end revision of a visibility constraint"
652
(or (revision-interval-end-date-time version) |rdf|:|nil|))
654
(defun |dydra|:|version-end-ordinal| (&optional (version (|dydra|:|version|)))
655
"This function returns the IRI of the end revision of a visibility constraint"
656
(or (revision-interval-end-ordinal version) |rdf|:|nil|))
658
(defun |dydra|:|version-end-uuid| (&optional (version (|dydra|:|version|)))
659
"This function returns the IRI of the end revision of a visibility constraint"
660
(or (revision-interval-end-uuid version) |rdf|:|nil|))
663
(defun |dydra|:|version-start-date-time| (&optional (version (|dydra|:|version|)))
664
"This function returns the IRI of the start revision of a visibility constraint"
665
(revision-interval-start-date-time version))
667
(defun |dydra|:|version-start-ordinal| (&optional (version (|dydra|:|version|)))
668
"This function returns the IRI of the start revision of a visibility constraint"
669
(revision-interval-start-ordinal version))
671
(defun |dydra|:|version-start-uuid| (&optional (version (|dydra|:|version|)))
672
"This function returns the IRI of the start revision of a visibility constraint"
673
(revision-interval-start-uuid version))
677
(defun |dydra|:|revision-signature| ()
678
"This function returns a digest signature of the query's active revision.
679
If none is available, it returns rdf:nil"
681
(let ((signature (revision-signature (task-transaction *task*))))
683
(vector (intern-iri (format nil "urn:hash::sha256:~a" (binascii:encode signature :base32))))
687
(defun |dydra|:|revision-uri| (&optional revision)
688
"This function returns the IRI of the current query's active revision"
690
(null (or (when *task* (revision-uri (task-transaction *task*)))
691
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision-uri|))))
692
(integer (let ((record (rlmdb:get-revision-uuid *repository* revision)))
694
(rlmdb:revision-record-uuid record)
695
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision-uri|)))))
697
(load-time-value (spocq:make-unbound-variable '|dydra|:|revision-uri|)))))
699
(defun |dydra|:|transaction-uri| ()
700
"This function returns the IRI of the current query's active transaction."
701
(or (when *task* (transaction-uri (task-transaction *task*)))
702
(load-time-value (spocq:make-unbound-variable '|dydra|:|transaction-uri|))))
704
(defun |dydra|:|user-tag| ()
706
(task-user-tag *task*))
707
(load-time-value (spocq:make-unbound-variable '|dydra|:|user-tag|))))
709
;;; if the situation allows, return the term number driectly, otherwise concert.
710
;;; the fomer matters in those cases where the attempt to convert the term to the interned value would signal an error.
712
(defun |dydra|::|term-number| (object)
713
(repository-object-term-number *transaction* object))
715
(define-compiler-macro |dydra|::|term-number| (expression &environment env)
716
"if possible, return the value in-line, other wise delegate to the object-based execution."
717
(let ((expression-expansion (macroexpand-1 expression env)))
718
(if (field-object-aref-p expression-expansion)
719
`(aref ,@(field-object-aref-aref expression-expansion))
724
(defpackage "http://dydra.com/list-processing#"
734
(cl-user::add-iri-package "http://dydra.com/list-processing#")
737
(defun rdf-match-object (&key (wild (repository-wildcard-term *transaction*))
741
(flet ((decode-term (c s p o)
742
(declare (ignore c s p))
743
(return-from rdf-match-object o)))
744
(declare (dynamic-extent #'decode-term))
745
(repository-call-with-matched-terms #'decode-term *transaction* s p wild :context g)
746
;; if it returns, then nothing matched
749
(defun rdf-match-subject (&key (wild (repository-wildcard-term *transaction*))
753
(flet ((decode-term (c s p o)
754
(declare (ignore c p o))
755
(return-from rdf-match-subject s)))
756
(declare (dynamic-extent #'decode-term))
757
(repository-call-with-matched-terms #'decode-term *transaction* wild p o :context g)
758
;; if it returns, then nothing matched
762
(defun rdf-first (cons-term)
763
(if (or (eql cons-term +null-term+)
764
(eql cons-term (symbol-term-id |rdf|:|nil|)))
766
(rdf-match-object :s cons-term :p (symbol-term-id |rdf|:|first|))))
768
(defun rdf-rest (cons-term)
769
(if (or (eql cons-term +null-term+)
770
(eql cons-term (symbol-term-id |rdf|:|nil|)))
772
(rdf-match-object :s cons-term :p (symbol-term-id |rdf|:|rest|))))
774
(defun rdf-nthcdr (index cons-term)
775
(let ((nil-term (symbol-term-id |rdf|:|nil|)))
776
(labels ((rdf-nthcdr-aux (index cons-term)
777
(if (or (not (plusp index))
778
(eql cons-term nil-term)
779
(eql cons-term +null-term-id+))
781
(rdf-nthcdr-aux (1- index) (rdf-rest cons-term)))))
782
(rdf-nthcdr-aux index cons-term))))
784
(defun rdf-last (cons-term &optional (index 1))
785
(loop with nil-term = (symbol-term-id |rdf|:|nil|)
786
with cells = (list cons-term)
787
do (setf cons-term (rdf-rest cons-term)
788
cells (cons cons-term cells))
789
until (or (eql cons-term nil-term)
790
(eql cons-term +null-term-id+))
791
finally (return (or (nth index cells) nil-term))))
794
(defun |lisp|:|first| (resource)
795
"Return the cons cell first object or the null term if either the resource does not
796
exist or matches no such assertion."
797
(let ((cons (rlmdb:value-term-number resource :if-does-not-exist nil)))
799
(rlmdb:term-number-value (rdf-first cons))
800
(symbol-term-id |rdf|:|nil|))))
802
(defun |lisp|:|rest| (resource)
803
"Return the cons cell rest object or the null term if either the resource does not
804
exist or matches no such assertion."
805
(let ((cons (rlmdb:value-term-number resource :if-does-not-exist nil)))
807
(rlmdb:term-number-value (rdf-rest cons))
808
(symbol-term-id |rdf|:|nil|))))
810
(defun |lisp|::|nth| (resource index)
811
(let ((nthcdr-term (rdf-nthcdr index (rlmdb:value-term-number resource))))
812
(cond ((eql nthcdr-term (symbol-term-id |rdf|:|nil|))
814
((eql nthcdr-term +null-term-id+)
815
(rlmdb:term-number-value +null-term-id+))
817
(rlmdb:term-number-value (rdf-match-object :s nthcdr-term
818
:p (symbol-term-id |rdf|:|first|)))))))
821
(defun |lisp|:|nthcdr| (index resource)
822
(let ((nthcdr-term (rdf-nthcdr index (rlmdb:value-term-number resource))))
823
(cond ((eql nthcdr-term (symbol-term-id |rdf|:|nil|))
826
(rlmdb:term-number-value nthcdr-term)))))
829
(defun |lisp|:|last| (resource &optional (count 0))
830
(let ((last-term (rdf-last (rlmdb:value-term-number resource) count)))
831
(cond ((eql last-term (symbol-term-id |rdf|:|nil|))
834
(rlmdb:term-number-value last-term)))))
837
(defun |lisp|:|member| (resource element)
838
(let ((element-id (rlmdb:value-term-number element)))
839
(if (eql element-id +null-term-id+)
841
(loop for resource-id = (rlmdb:value-term-number resource)
842
then (rdf-rest resource-id)
843
when (or (eql resource-id (symbol-term-id |rdf|:|nil|))
844
(eql resource-id +null-term-id+))
846
when (eql element-id (rdf-match-object :s resource-id
847
:p (symbol-term-id |rdf|:|first|)))
848
return (rlmdb:term-number-value resource-id)))))
852
(defgeneric |dydra|:|documentation| (function)
853
(:documentation "Iff the term binds a function, return its documentation string.
854
If unbound or undocumented, return a zero length string")
855
(:method ((function symbol))
856
(if (and (fboundp function) (symbol-term-id function))
857
(documentation function 'function)
859
(:method ((function t))
862
(defun |dydra|:|build-revision| ()
863
"Return the source version identifier for the active server"
866
(defun |dydra|:|build-timestamp| ()
867
"Return the unix timestamp of the build for the active server"
868
(universal-time-timeline-location (decode-iso-time *build-timestamp*)))
870
(defun |dydra|:|build-date-time| ()
871
"Return the dateTime of the build for the active server"
872
(universal-time-date-time (decode-iso-time *build-timestamp*)))