Coverage report: /development/source/library/org/datagraph/spocq-shard/src/store/rdfcache/rdfcache.lisp
| Kind | Covered | All | % |
| expression | 186 | 271 | 68.6 |
| branch | 22 | 36 | 61.1 |
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 "store api additions for query/update processing"
6
"This includes mechanisms to intern/externailze object relative to rdf cache.")
9
(unless (fboundp 'rdfcache::is-string)
10
(defun rdfcache::is-string (term-number)
11
(and (eq (rdfcache:fetch-term-type term-number) :literal)
12
(eql 0 (dydra-ndk:term-datatype-id term-number)))))
14
(defmacro rdfcache-match (transaction cursor context subject predicate object)
15
`(progn (incf *match-requests*)
16
(rdfcache:match ,transaction ,cursor ,context ,subject ,predicate ,object)))
19
(defmacro rdfcache-match (transaction cursor context subject predicate object)
24
(print-term-strings .c.)
25
(print-term-strings .s.)
26
(print-term-strings .p.)
27
(print-term-strings .o.)
29
(rdfcache:match ,transaction ,cursor .c. .s. .p. .o.)))
32
;;; libdydra error in rdfcache_ffi_count: Input/output error (errno=5) unknown transaction: 4749cc49-d7a2-11ea-b9ca-901b0e95d742
33
;;; wrapped counts to muffle the error
34
;;; did not do the same for next as they are much more frequent and wrapping each in an error handler would be
35
;;; too slow. if anything, this should end up in the bgp processing operator, to have it just complete the scan
38
(defmacro rdfcache-count (transaction-record context subject predicate object)
39
`(rdfcache:count ,transaction-record ,context ,subject ,predicate ,object))
41
(defun rdfcache-count (transaction-record context subject predicate object)
43
(rdfcache:count transaction-record context subject predicate object)
45
(log-error "rdfcache-count: ignored error: ~a" c)
48
(defmacro rdfcache-declare-terms (cursor context subject predicate object)
49
`(rdfcache:declare-terms ,cursor ,context ,subject ,predicate ,object))
51
(defmacro rdfcache-next (cursor)
52
`(rdfcache:next ,cursor))
55
#+(or) ; patch for possible race - replaced with general lock
57
(defparameter *rdfcache-fetch-term* (symbol-function 'rdfcache:fetch-term*))
58
(defparameter *rdfcache-fetch-term-lock* nil)
59
(defun rdfcache-fetch-term-lock ()
60
(or *rdfcache-fetch-term-lock*
61
(setq *rdfcache-fetch-term-lock* (bt:make-lock))))
62
(defun rdfcache:fetch-term* (&rest args)
63
(let ((lock (rdfcache-fetch-term-lock)))
64
(bt:with-lock-held (lock)
65
(apply *rdfcache-fetch-term* args))))
70
(defmacro rdfcache-match (transaction cursor context subject predicate object)
71
`(rdfcache-match-verbose-id ,transaction ,cursor ,context ,subject ,predicate ,object))
73
(defmacro rdfcache-count (transaction context subject predicate object)
74
`(rdfcache-count-verbose-id ,transaction ,context ,subject ,predicate ,object))
76
(defmacro rdfcache-next (cursor)
77
`(rdfcache-next-verbose-id ,cursor))
81
(defmacro with-terms (term-bindings &rest body)
82
(macroexpand-with-terms term-bindings body))
84
(defun macroexpand-with-terms (term-bindings body)
85
(let* ((body-proper (member 'declare body :key #'first :test-not #'eq))
86
(declarations (ldiff body body-proper))
87
(term-variables (mapcar #'first term-bindings))
88
(term-forms (mapcar #'second term-bindings))
89
(body-form `(progn ,@body-proper))
91
`(cffi:with-foreign-objects ,(mapcar #'(lambda (variable) `(,variable '(:struct rdfcache::term))) term-variables)
94
,(loop for term-variable in term-variables
95
for term-form in term-forms
97
(multiple-value-bind (bindings initializations finalizations)
98
(compute-term-initializer term-variable term-form)
99
(setf unwind-clauses (append unwind-clauses finalizations))
101
(destructuring-bind (op bindings) bindings
102
`(,op ,bindings ,@initializations
103
;; ,@(mapcar #'(lambda (var) `(intern-term ,var)) term-variables)
106
`(progn ,@initializations
107
;; ,@(mapcar #'(lambda (var) `(intern-term ,var)) term-variables)
111
finally (return body-form))
115
(defmacro with-pattern-term-numbers (term-bindings &body body)
116
"Establish a contour in which each variable is bound to
117
- a term number when the respective form is a literal or uri constant
118
- the wildcard term number if the respective form is a variable or a blank node"
119
(let ((x-action (gensym "transaction"))
120
(coerce (gensym "coerce")))
121
`(let* ((,x-action (transaction-record *transaction*)))
122
(flet ((,coerce (term)
123
(if (or (null term) (spocq:blank-node-p term) (variable-p term))
124
rdfcache:*wildcard-term-number*
125
(rdfcache-object-term-number ,x-action term))))
126
(let ,(loop for (variable expression) in (mapcar #'(lambda (b) (if (consp b) b (list b b))) term-bindings)
127
collect `(,variable (,coerce ,expression)))
130
(defvar *rdfcache-timeout* 2000)
133
(defmethod initialize-store ((repository rdfcache-repository) (store-uri t) (store-library t))
134
(handler-bind ((warning #'muffle-warning))
135
(rdfcache:load-library :path store-library))
137
;; bind vocabulary uri objects to their lexical and store designators
138
(initialize-interned-terms )
139
#+(or) ;; all term-number-object access now directly through rlmdb
140
(define-rdfcache-typed-term-number-object-methods)
143
(defmethod reinitialize-store ((repository rdfcache-repository))
149
;;; (cffi:close-foreign-library (first (CFFI:LIST-FOREIGN-LIBRARIES)))
152
(cffi:defcallback signal-error :void ((message :pointer))
153
(error 'rdfcache::rdfcache-error
154
:format-control "signalled from rdfcache internals: ~a."
155
:format-arguments (list (cffi::foreign-string-to-lisp message))))
157
(defclass store () ())
159
(defclass rdfcache-store (store) ())
161
(defparameter *connection-timeout* 500)
164
(defclass rdfcache-store (store)
165
((query-operator :initform 'rdfcache::query :initarg :query-operator
166
:reader test-store-query-operator)))
168
(undefun call-with-rdfcache-cursor (op)
169
(declare (dynamic-extent op))
170
(with-cursor-record (%cursor)
171
(rdfcache::%clear-cursor %cursor)
172
(unwind-protect (funcall op %cursor)
173
(rdfcache:close %cursor))))
177
(undefmethod transaction-call-with-matched-terms (op (transaction rdfcache-transaction) subject predicate object &key (context (repository-wildcard-term *transaction*))
178
(target-graph nil) (ordered-p nil))
179
(let* ((%transaction (transaction-record transaction))
180
(%match-cursor (rdfcache::make-quad-cursor %transaction context subject predicate object
181
:graph target-graph :ordered ordered-p)))
183
(loop (unless (dydra-ndk::quad-cursor-next %match-cursor) (return))
185
(dydra-ndk::quad-cursor-graph-id %match-cursor)
186
(dydra-ndk::quad-cursor-subject-id %match-cursor)
187
(dydra-ndk::quad-cursor-predicate-id %match-cursor)
188
(dydra-ndk::quad-cursor-object-id %match-cursor)))
190
(dydra-ndk::free-quad-cursor %match-cursor)))))
195
(undefmethod repository-pattern-count ((repository rdfcache-repository) subject predicate object context)
196
(let ((stats (repository-statistics repository))
197
(pattern (list subject predicate object context)))
198
(declare (dynamic-extent pattern))
199
(if (operation-read-only-p *task*)
200
(or (gethash pattern stats)
201
(setf (get-registry (copy-list pattern) stats)
202
(read-repository-pattern-count repository subject predicate object context)))
203
(read-repository-pattern-count repository subject predicate object context))))
205
(undefmethod read-repository-pattern-count ((repository rdfcache-repository) subject predicate object context)
206
;; ensure that the repository has at least one commit and that it is bound to a concrete store
207
(if (and (repository-revision-id repository)
208
(repository-store-uri repository))
209
(flet ((read-pattern-count ()
210
(repository-pattern-count *transaction* subject predicate object context)))
213
(with-open-transaction (repository) (read-pattern-count))))
214
;; otherwise, it is empty
217
(undefmethod repository-pattern-count ((transaction rdfcache-transaction) subject predicate object context)
218
(let* ((x-record (transaction-record transaction))
219
(context (case context
221
rdfcache:*wildcard-term-number*)
223
(repository-all-contexts-term-number transaction)) ;;
224
(|urn:dydra|:|default| ;; (|urn:dydra|:|default| nil)
225
(repository-default-context-term-number transaction))
227
(repository-named-contexts-term-number transaction))
229
(if (variable-p context)
230
(ecase (named-contexts-term)
231
(|urn:dydra|:|all| (repository-all-contexts-term-number transaction))
232
(|urn:dydra|:|default| (repository-default-context-term-number transaction))
233
(|urn:dydra|:|named| (repository-named-contexts-term-number transaction)))
234
(rdfcache-object-term-number x-record context))))))
235
(with-pattern-term-numbers (subject predicate object)
236
(rdfcache-count x-record context subject predicate object))))
238
;;; (defmethod repository-pattern-count :before ((transaction rdfcache-transaction) subject predicate object context) (print "repository-pattern-count: xaction") (rdfcache:print-transaction (transaction-record transaction)))
240
(undefmethod read-repository-statement-count ((repository rdfcache-repository))
241
;; ensure that the repositry has at least one commit ans that it is bounds to a concrete store
242
(if (and (repository-revision-id repository)
243
(repository-store-uri repository))
244
(flet ((read-statement-count ()
245
(rdfcache-count (transaction-record *transaction*) (repository-all-contexts-term-number repository)
246
rdfcache:*wildcard-term-number* rdfcache:*wildcard-term-number* rdfcache:*wildcard-term-number*)))
248
(read-statement-count)
249
(with-open-transaction (repository) (read-statement-count))))
252
(undefmethod read-repository-statement-count ((transaction rdfcache-transaction))
253
;; ensure that the repositry has at least one commit ans that it is bounds to a concrete store
254
(rdfcache-count (transaction-record transaction) rdfcache:*all-context-number*
255
rdfcache:*wildcard-term-number* rdfcache:*wildcard-term-number* rdfcache:*wildcard-term-number*))
256
(undefmethod read-repository-statement-count ((transaction rdfcache-transaction))
261
(undefun rdfcache-context-term-number (transaction context)
263
((nil t :default) (repository-default-context-term-number transaction))
264
(|urn:dydra|:|default| rdfcache:*default-context-number*)
265
(|urn:dydra|:|named| rdfcache:*named-context-number*)
266
(|urn:dydra|:|all| rdfcache:*all-context-number*)
268
(cond ((iri-p context)
269
(rdfcache-object-term-number transaction context))
271
(log-warn "invalid context term: ~s." context)
274
(undefmethod repository-context-term-number ((repository-handle rdfcache-transaction) context)
275
(rdfcache-context-term-number repository-handle context))
276
(undefmethod repository-context-term-number ((repository-handle rdfcache-repository) context)
277
(rdfcache-context-term-number *transaction* context))
280
(undefmethod map-repository-contexts (function (repository-handle rdfcache-transaction) &key
283
;;(declare (dynamic-extent function))
284
(declare (ignore default))
285
(rdfcache:map-context-numbers function (transaction-record repository-handle) :distinct distinct))
288
(undefmethod map-repository-subjects (function (repository-handle rdfcache-transaction) &key
289
(context nil) (distinct t))
290
(declare (dynamic-extent function))
291
(rdfcache:map-subject-numbers function (transaction-record repository-handle)
293
:context (rdfcache-context-term-number repository-handle context)))
295
(undefgeneric map-repository-context-subjects (function repository-handle context &key distinct)
296
(:method (function (repository-handle rdfcache-transaction) (context integer) &key (distinct t))
297
#-sbcl (declare (dynamic-extent function))
298
(rdfcache:map-subject-numbers function (transaction-record repository-handle)
301
(:method (function (repository-handle rdfcache-transaction) (context t) &key (distinct t))
302
#-sbcl (declare (dynamic-extent function))
303
(map-repository-context-subjects function repository-handle (rdfcache-context-term-number repository-handle context)
305
(:method (function (repository-handle rdfcache-transaction) (context cons) &key (distinct t))
306
#-sbcl (declare (dynamic-extent function))
307
(loop for context in context
308
do (map-repository-context-subjects function repository-handle context :distinct distinct))))
310
(undefgeneric map-repository-subjects-and-contexts (continuation repository-handle context &key distinct)
311
(:method (continuation (repository-handle rdfcache-transaction) (context integer) &key (distinct t))
312
#-sbcl (declare (dynamic-extent function))
313
(flet ((continue-with-context (subject)
314
(funcall continuation context subject)))
315
(declare (dynamic-extent #'continue-with-context))
316
(rdfcache:map-subject-numbers #'continue-with-context (transaction-record repository-handle)
319
(:method (continuation (repository-handle rdfcache-transaction) (context t) &key (distinct t))
320
#-sbcl (declare (dynamic-extent continuation))
321
(map-repository-subjects-and-contexts continuation repository-handle (rdfcache-context-term-number repository-handle context)
323
(:method (continuation (repository-handle rdfcache-transaction) (context cons) &key (distinct t))
324
#-sbcl (declare (dynamic-extent continuation))
325
(loop for context in context
326
do (map-repository-subjects-and-contexts continuation repository-handle context :distinct distinct))))
330
(undefmethod map-repository-predicates (function (repository-handle rdfcache-transaction) &key
331
(context nil) (distinct t))
332
(declare (dynamic-extent function))
333
(rdfcache:map-predicate-numbers function (transaction-record repository-handle)
335
:context (rdfcache-context-term-number repository-handle context)))
337
(undefmethod map-repository-objects (function (repository-handle rdfcache-transaction) &key
338
(context nil) (distinct t))
339
; (declare (dynamic-extent function))
340
(rdfcache:map-object-numbers function (transaction-record repository-handle)
342
:context (rdfcache-context-term-number repository-handle context)))
344
(undefgeneric map-repository-context-objects (function repository-handle context &key distinct)
345
(:method (function (repository-handle rdfcache-transaction) (context integer) &key (distinct t))
346
#-sbcl (declare (dynamic-extent function))
347
(rdfcache:map-object-numbers function (transaction-record repository-handle)
350
(:method (function (repository-handle rdfcache-transaction) (context t) &key (distinct t))
351
#-sbcl (declare (dynamic-extent function))
352
(map-repository-context-objects function repository-handle (rdfcache-context-term-number repository-handle context)
354
(:method (function (repository-handle rdfcache-transaction) (context cons) &key (distinct t))
355
#-sbcl (declare (dynamic-extent function))
356
(loop for context in context
357
do (map-repository-context-objects function repository-handle context :distinct distinct))))
359
(undefgeneric map-repository-objects-and-contexts (continuation repository-handle context &key distinct)
360
(:method (continuation (repository-handle rdfcache-transaction) (context integer) &key (distinct t))
361
#-sbcl (declare (dynamic-extent function))
362
(flet ((continue-with-context (obbject)
363
(funcall continuation context obbject)))
364
(declare (dynamic-extent #'continue-with-context))
365
(rdfcache:map-object-numbers #'continue-with-context (transaction-record repository-handle)
368
(:method (continuation (repository-handle rdfcache-transaction) (context t) &key (distinct t))
369
#-sbcl (declare (dynamic-extent function))
370
(map-repository-objects-and-contexts continuation repository-handle (rdfcache-context-term-number repository-handle context)
372
(:method (continuation (repository-handle rdfcache-transaction) (context cons) &key (distinct t))
373
#-sbcl (declare (dynamic-extent continuation))
374
(loop for context in context
375
do (map-repository-objects-and-contexts continuation repository-handle context :distinct distinct))))
377
(undefmethod map-repository-terms (function (transaction rdfcache-transaction) context key declarations &key (distinct t))
378
;; (declare (dynamic-extent function)) ; gets sbcl upset
379
(flet ((iterate-with-context (%context)
380
(let ((wildcard-term (repository-wildcard-term (transaction-repository transaction))))
381
(with-cursor-record (%cursor)
382
(rdfcache::term-cursor-init %cursor
383
(if distinct rdfcache::RDFCACHE_TERM_CURSOR_DISTINCT 0)
385
(unwind-protect (progn (rdfcache::term-cursor-open (transaction-record transaction) %cursor %context)
386
(loop (unless (rdfcache:term-cursor-next %cursor) (return))
387
(funcall function (rdfcache:curor-term-number %cursor))))
388
(rdfcache:term-cursor-close %cursor))))))
389
(when (transaction-parent-p transaction)
390
;; iff it is not empty
393
(iterate-with-context (repository-default-context-term-number (transaction-repository transaction))))
395
(iterate-with-context context))))))
397
(undefmethod map-repository-statements (function (transaction rdfcache-transaction) subject predicate object context &key offset count)
398
(let ((wildcard-term (repository-wildcard-term (transaction-repository transaction))))
399
(with-cursor-record (%cursor)
400
(rdfcache::%clear-cursor %cursor)
401
(unwind-protect (when (plusp (rdfcache-match (transaction-record transaction) %cursor
402
(or context (repository-default-context-term-number (transaction-repository transaction)))
403
(or subject wildcard-term)
404
(or predicate wildcard-term)
405
(or object wildcard-term)))
406
(rdfcache::declare-terms %cursor :term-number :term-number :term-number :term-number)
407
(loop (unless (rdfcache-next %cursor) (return))
408
(cond ((and offset (plusp offset))
411
(when (and count (minusp (decf count)))
414
(rdfcache::cursor-context-number %cursor)
415
(rdfcache::cursor-subject-number %cursor)
416
(rdfcache::cursor-predicate-number %cursor)
417
(rdfcache::cursor-object-number %cursor))))))
418
(rdfcache:close %cursor)))))
423
(defmethod repository-delete-field ((repository rdfcache-repository) (solution-field t))
424
(repository-delete-field *transaction* solution-field))
426
(defmethod repository-delete-field ((transaction rdfcache-transaction) (solution-field list))
428
(repository-delete-field transaction (repository-intern-statements transaction solution-field))
431
(defmethod repository-delete-field ((context t) (solution-field vector))
432
(loop for field across solution-field
433
sum (repository-delete-field context field)))
435
(defmethod repository-delete-field ((transaction rdfcache-transaction) (solution-field array))
436
(trace-algebra repository-delete-field transaction solution-field (term-value-field solution-field))
437
(assert-argument-type repository-delete-field solution-field
438
(or (simple-array fixnum (* 3)) (simple-array fixnum (* 4))))
439
(let ((%transaction (transaction-record transaction))
440
(provenance-p (case *provenance-mode*
441
(|urn:dydra|:|none| nil)
442
(t (when (task-provenance-repository *task*) t)))))
443
(ecase (array-dimension solution-field 1)
444
(3 (do-solution-field (subject predicate object) solution-field
445
(when (and (> subject 0) (> predicate 0) (> object 0))
446
(rdfcache::delete-statement %transaction rdfcache:*default-context-number*
447
subject predicate object))))
448
(4 (let ((field-graph 0))
449
;; modify the id list for any graph which appears
450
(do-solution-field (subject predicate object graph) solution-field
451
(when (and (> subject 0) (> predicate 0) (> object 0)
452
(or (> graph 0) (= graph rdfcache:*default-context-number*)))
453
(when (and provenance-p (/= graph field-graph))
454
(setf field-graph graph)
455
(setf (transaction-graph-id-modified *transaction* graph) t))
456
(record-modified-resource transaction subject)
457
(rdfcache::delete-statement %transaction graph
458
subject predicate object))))))
459
(array-dimension solution-field 0)))
462
(defmethod repository-insert-field ((repository rdfcache-repository) (solution-field t))
463
(repository-insert-field *transaction* solution-field))
465
(defmethod repository-insert-field ((transaction rdfcache-transaction) (solution-field list))
467
(repository-insert-field transaction (repository-intern-statements transaction solution-field))
470
(defmethod repository-insert-field ((context rdfcache-transaction) (solution-field vector))
471
(loop for field across solution-field
472
sum (repository-insert-field context field)))
474
(defmethod repository-insert-field ((transaction rdfcache-transaction) (solution-field array))
475
"Insert the given statements from the repository. If given triples (v/s quads) then add
476
the statements to the static default graph, without allowing for the default/named/all option.
477
When given quads, use ther s-p-o-g order as for sexp-quads."
478
(ecase (array-rank solution-field)
479
#+(or) ;; obsolete. see above
480
(1 (loop for solution-field-page across solution-field
481
sum (repository-insert-field transaction solution-field-page)))
483
(trace-algebra repository-insert-field (repository-id transaction) solution-field (term-value-field solution-field))
484
(assert-argument-type repository-insert-field solution-field
485
(or (simple-array fixnum (* 3)) (simple-array fixnum (* 4))))
486
(let ((%transaction (transaction-record transaction))
487
(provenance-p (case *provenance-mode*
488
(|urn:dydra|:|none| nil)
489
(t (when (task-provenance-repository *task*) t)))))
490
(ecase (array-dimension solution-field 1)
491
(3 (do-solution-field (subject predicate object) solution-field
492
(rdfcache::insert-statement %transaction rdfcache:*default-context-number*
493
subject predicate object)))
494
(4 (let ((field-graph 0) (*print-right-margin* 144)
495
(rdf-type-term-id (symbol-term-id '|rdf|:|type|)))
496
;; modify the id list for any graph which appears
497
(do-solution-field (subject predicate object graph) solution-field
498
(when (and (/= subject 0) (/= predicate 0) (/= object 0) (/= graph 0))
499
(when (and provenance-p (/= graph field-graph))
500
(setf field-graph graph)
501
(if (or (not (plusp graph)) (zerop (rdfcache-count %transaction graph 0 0 0)))
502
(setf (transaction-graph-id-created *transaction* graph) t)
503
(setf (transaction-graph-id-modified *transaction* graph) t)))
504
(if (= predicate rdf-type-term-id)
505
(record-new-resource transaction subject)
506
(record-modified-resource transaction subject))
509
(write-to-string (list (rdfcache-term-number-object %transaction subject)
510
(rdfcache-term-number-object %transaction predicate)
511
(rdfcache-term-number-object %transaction object)
512
(rdfcache-term-number-object %transaction graph))))
513
(rdfcache::insert-statement %transaction graph subject predicate object))))))
514
(array-dimension solution-field 0)))))
516
;;; matrix operations
518
(undefmethod repository-matrix-field ((transaction rdfcache-transaction) context subject predicate object
521
"generate a new solution matrix for the statements which match the argument pattern.
522
If the context is not yet interned, intern all terms and recurse. should some term not be present, then return
523
a null matrix. Associate a (possible sparse) dimension list with the result to indicate which columns
526
(declare (dynamic-extent args))
527
(let ((%transaction (transaction-record transaction))
528
(wildcard-term (repository-wildcard-term transaction)))
531
(rdfcache:with-cursor (%quad-cursor)
532
(let* ((quad-cursor-count (rdfcache-match %transaction %quad-cursor
533
context subject predicate object))
534
(%quad-matrix (rdfcache:cursor-to-matrix %transaction %quad-cursor
536
:row-limit (when end (- end start)))))
537
(make-matrix-field :solutions %quad-matrix :data (rdfcache:matrix-data-pointer %quad-matrix)
538
:row-count quad-cursor-count :row-index -1))))
540
(flet ((coerce-variable (term &optional (default nil))
541
(if (variable-p term) term default)))
542
;; always provide a context binding to make it available to joins so that patterns
543
;; do not cross graph boundaries
544
(let* ((dimensions (list (coerce-variable context +context-variable+)
545
(coerce-variable subject) (coerce-variable predicate) (coerce-variable object)))
546
(sort-dimensions (remove nil dimensions)))
547
(flet ((coerce-term (term)
548
(if (or (null term) (spocq:blank-node-p term) (variable-p term))
549
wildcard-term ; rdfcache:*wildcard-term-number*
550
(or (rdfcache-lookup-object-term-number term)
551
(return-from repository-matrix-field (make-null-matrix sort-dimensions))))))
553
(apply #'repository-matrix-field transaction
554
(coerce-term context) (coerce-term subject) (coerce-term predicate) (coerce-term object)
556
(setf (matrix-field-dimensions matrix-field) dimensions
557
(matrix-field-sort-dimensions matrix-field) sort-dimensions)
560
(undefmethod repository-match-field ((transaction rdfcache-transaction) context subject predicate object &rest args)
561
(let ((field (apply #'repository-matrix-field transaction context subject predicate object args)))
562
(prog1 (term-value-field field)
563
(release-field-data field))))
565
(undefmethod repository-matrix-field ((transaction rdfcache-transaction) context subject predicate object
566
&key (start 0) end dimensions (wild-blank-nodes-p t))
567
"generate a new solution matrix for the statements which match the argument pattern.
568
If the context is not yet interned, intern all terms and recurse. should some term not be present, then return
569
a null matrix. Associate a (possible sparse) dimension list with the result to indicate which columns
571
The result field elements are ordered (c s p o)"
573
(let* ((%transaction (transaction-record transaction))
574
(wildcard-term (repository-wildcard-term transaction))
575
(default-context-term (repository-default-context-term transaction))
576
(dataset (task-dataset-graphs *task*))
578
(cond ((null context) (if dataset (dataset-default-graphs dataset) (list default-context-term)))
579
((variable-p context) (dataset-named-graphs dataset))
580
((typep context 'iri) (list context))
582
(error "Invalid dataset specification: graph ~s, dataset ~s."
584
(flet ((coerce-variable (term &optional (default nil))
585
(if (variable-p term) term default)))
586
(rdfcache:with-cursor (%quad-cursor)
587
;;!! the dimension construction should have the effect, that, it retains the
588
;;!! variable in the in the scope of a graph form only
589
;;!! given 'all' graphs, the grap terms should be ignored.
590
;; always provide a context binding to make it available to joins so that patterns
591
;; do not cross graph boundaries
592
(let* ((dimensions (or dimensions
593
(list (coerce-variable context nil) ;; +context-variable+)
594
(coerce-variable subject) (coerce-variable predicate) (coerce-variable object))))
595
(sort-dimensions (remove nil dimensions)))
596
(flet ((coerce-term (term)
597
(if (or (null term) (and (spocq:blank-node-p term) wild-blank-nodes-p) (variable-p term))
599
(or (rdfcache-lookup-object-term-number term)
600
;; if the term is not in the store, no match is possible
601
(return-from repository-matrix-field (make-null-matrix sort-dimensions))))))
602
(let ((interned-subject (coerce-term subject))
603
(interned-predicate (coerce-term predicate))
604
(interned-object (coerce-term object)))
605
(flet ((match-context (interned-effective-context)
606
(let ((count (rdfcache-count %transaction
607
interned-effective-context
608
interned-subject interned-predicate interned-object)))
610
(rdfcache-match %transaction %quad-cursor
611
interned-effective-context
612
interned-subject interned-predicate interned-object)
613
(rdfcache:cursor-to-matrix %transaction %quad-cursor
615
:row-limit (- (or end count) start)))))
616
(count-context (interned-effective-context)
617
(repository-pattern-count transaction
618
interned-subject interned-predicate interned-object
619
interned-effective-context)))
620
;; manage the count separately rather than using the matrix sizes to allow
621
;; for eventual streaming
622
;; (print (cons :effective-contexts effective-contexts))
623
(let* ((interned-effective-contexts (loop for context in effective-contexts
624
for interned-context = (case context
625
(|urn:dydra|:|all| rdfcache:*all-context-number*)
626
(|urn:dydra|:|default| rdfcache:*default-context-number*)
627
(|urn:dydra|:|named| rdfcache:*named-context-number*)
628
(t (rdfcache-lookup-object-term-number context)))
629
;; if it is not known, there can be no result
630
when interned-context
631
collect interned-context))
632
(%accumulated-matrix nil))
633
;; (print (cons :interned-effective-contexts interned-effective-contexts))
634
(loop for interned-context in interned-effective-contexts
635
for %matrix = (match-context interned-context)
637
(cond (%accumulated-matrix
638
(setf %accumulated-matrix (rdfcache::matrix-concatenate %accumulated-matrix %matrix))
639
(rdfcache:matrix-release %matrix))
641
(setf %accumulated-matrix %matrix)))))
642
(if %accumulated-matrix
643
(make-matrix-field :solutions %accumulated-matrix
644
:row-count (rdfcache:matrix-row-count %accumulated-matrix)
646
:dimensions dimensions
647
:sort-dimensions sort-dimensions
648
:count (rdfcache:matrix-row-count %accumulated-matrix))
649
(make-matrix-field :row-count 0 :row-index 0
650
:dimensions dimensions
651
:sort-dimensions sort-dimensions
654
(undefmethod repository-match-matrix ((transaction rdfcache-transaction) matrix context subject predicate object
656
"generate a new solution matrix for the statements which match the argument pattern.
657
If the context is not yet interned, intern all terms and recurse. should some term not be present, then return
658
a null matrix. Associate a (possible sparse) dimension list with the result to indicate which columns
661
(let* ((%transaction (transaction-record transaction))
662
(contexts (if (consp context) context (list context)))
663
(result-matrix (if (and matrix (not (cffi:null-pointer-p matrix)))
665
(rdfcache:make-matrix 0 4)))
668
(limit (when end (- end start))))
669
(rdfcache:with-cursor (%quad-cursor)
670
(flet ((match-context (context)
671
(when (plusp (rdfcache-match %transaction %quad-cursor context subject predicate object))
672
;; accept a possibly replace matrix and track the count of matched solutions including those skipped
673
(multiple-value-bind (new-matrix count)
674
(rdfcache:cursor-append-matrix %transaction %quad-cursor result-matrix
675
:row-offset offset :row-limit limit)
676
(setf result-matrix new-matrix)
677
(incf result-count count)
678
(when (and limit (> count offset)) (decf limit (- count offset)))
679
(setf offset (max 0 (- offset count)))))))
680
(loop for context in contexts
681
until (and limit (<= limit 0))
682
do (match-context context))
683
(values result-matrix result-count)))))
685
;;; (trace repository-match-matrix rdfcache:make-matrix rdfcache:match rdfcache:cursor-append-matrix rdfcache::matrix-nconc rdfcache:matrix-free)