Coverage report: /development/source/library/org/datagraph/spocq-shard/src/store/rdfcache/term-number-field-cache.lisp
| Kind | Covered | All | % |
| expression | 0 | 789 | 0.0 |
| branch | 0 | 84 | 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)
6
(defmethod initialize-instance :after ((instance term-number-field-cache) &key statements)
7
"index the given filed by spoc"
8
(flet ((add-statement (index)
9
(flet ((index-statement (stmt hash key1 &optional key2)
11
(let ((key1-hash (or (gethash key1 hash) (setf (gethash key1 hash) (make-repository-index)))))
12
(push stmt (gethash key2 key1-hash)))
13
(push stmt (gethash key1 hash)))))
14
(let ((subject (aref statements index 0))
15
(predicate (aref statements index 1))
16
(object (aref statements index 2))
17
(graph (aref statements index 3)))
18
(index-statement index (cache-index-ps instance) predicate subject)
19
(index-statement index (cache-index-po instance) predicate object)
20
(index-statement index (cache-index-s instance) subject)
21
(index-statement index (cache-index-p instance) predicate)
22
(index-statement index (cache-index-o instance) object)
23
(index-statement index (cache-index-c instance) graph)))))
24
(loop for index below (array-dimension statements 0)
25
do (add-statement index))
26
(setf (slot-value instance 'statements) statements)))
28
(defmethod repository-make-transaction ((repository term-number-field-cache) &key &allow-other-keys)
29
(repository-transaction repository))
31
(defmethod repository-open-transaction ((repository term-number-field-cache) (transaction transaction))
34
(defmethod repository-close-transaction ((repository term-number-field-cache) (transaction transaction) disposition)
37
(defmethod update-repository-revision-id ((repository term-number-field-cache))
40
(defmethod read-repository-pattern-count ((repository term-number-field-cache) subject predicate object context)
41
(flet ((coerce-term (term)
42
(if (or (null term) (spocq:blank-node-p term) (variable-p term))
43
rdfcache:*wildcard-term-number*
44
(rdfcache-object-term-number nil term))))
45
(let ((context (cond ((null context) RDFCACHE:*DEFAULT-CONTEXT-NUMBER*)
46
((variable-p context) rdfcache:*wildcard-term-number*)
47
(t (rdfcache-object-term-number nil context))))
48
(subject (coerce-term subject))
49
(predicate (coerce-term predicate))
50
(object (coerce-term object)))
51
(count-term-number-field repository context subject predicate object))))
53
(defmethod REPOSITORY-WILDCARD-TERM ((repository term-number-field-cache))
54
(REPOSITORY-WILDCARD-TERM (repository-reference repository)))
56
(defmethod REPOSITORY-NAMED-CONTEXTS-TERM-NUMBER ((repository term-number-field-cache))
57
(REPOSITORY-NAMED-CONTEXTS-TERM-NUMBER (repository-reference repository)) )
59
(defmethod REPOSITORY-default-CONTEXT-TERM-NUMBER ((repository term-number-field-cache))
60
(REPOSITORY-default-CONTEXT-TERM-NUMBER (repository-reference repository)))
62
(defmethod repository-object-term-number ((repository term-number-field-cache) term)
63
(repository-object-term-number (repository-reference repository) term))
66
;;; hash cache implementation
68
(defmacro spoc-term-number-case ((subject predicate object context)
69
&key spoc spo (spo- spo) spc (sp-c spc) sp (sp-- sp)
70
soc (s-oc soc) so (s-o- so) sc (s--c sc) s (s--- s)
71
poc (-poc poc) po (-po- po) pc (-p-c pc) p (-p-- p)
72
oc (--oc oc) o (--o- o) c (---c c) all (---- all))
73
"Consists of a sequence of forms, each identified by a combination of statement components.
74
The arguments are a mediator, s sequence of constituent variable and a matching series of
75
constituent forms. If the mediator is not the constant nil, the variables are bound to the respective
76
repository value. If nil, to the forms direct value. Then that clause is evaluated which indicates the
77
non-null constituents. if no constituent is present, control passes to the :---- clause."
79
`(let ((.flags. (logior (if (= wildcard-term-number ,subject) 0 #b1000)
80
(if (= wildcard-term-number ,predicate) 0 #b0100)
81
(if (= wildcard-term-number ,object) 0 #b0010)
82
(if (<= ,context 0) 0 #b0001))))
103
(defmethod de.setf.resource:map-statements* (continuation (db term-number-field-cache) subject predicate object graph)
104
"The indexed repository tries to focus iteration over the respective index.
105
The indices are at three level, so the context constrain requires a test against the
106
matched statements' sources."
107
; (declare (dynamic-extent continuation))
108
(let ((statements (cache-statements db))
109
(wildcard-term-number (REPOSITORY-WILDCARD-TERM db))
110
(default-context-term-number (repository-default-context-term-number db))
111
(named-contexts-term-number (repository-named-contexts-term-number db)))
112
(labels ((triple-subject (index) (aref statements index 0))
113
(triple-predicate (index) (aref statements index 1))
114
(triple-object (index) (aref statements index 2))
115
(triple-graph (index) (aref statements index 3))
116
(continue-with-statement (index)
117
(let ((statement-graph (triple-graph index)))
118
(when (or (= wildcard-term-number graph)
119
(and (= named-contexts-term-number graph) (> statement-graph 0))
120
(and (= default-context-term-number graph) (= statement-graph default-context-term-number)))
121
(funcall continuation (triple-graph index) (triple-subject index) (triple-predicate index) (triple-object index)))))
122
(filter-statements-by-object-by-graph (statements)
123
(dolist (statement statements)
124
(when (and (= (triple-object statement) object)
125
(= (triple-graph statement) graph))
126
(continue-with-statement statement))))
127
(filter-statements-by-object (statements)
128
(dolist (statement statements)
129
(when (= (triple-object statement) object)
130
(continue-with-statement statement))))
131
(filter-statements-by-graph (statements)
132
(dolist (statement statements)
133
(when (= (triple-graph statement) graph)
134
(continue-with-statement statement))))
135
(map-list (statements)
136
(dolist (statement statements)
137
(continue-with-statement statement)))
138
(map-index (statements)
139
(loop for index below (array-dimension statements 0)
140
do (continue-with-statement index)))
141
(gethash-if (key hash)
142
(when hash (gethash key hash))))
144
(spoc-term-number-case (subject predicate object graph)
145
:spoc (filter-statements-by-object-by-graph (gethash-if subject (gethash predicate (cache-index-ps db))))
146
:spo (filter-statements-by-object (gethash-if subject (gethash predicate (cache-index-ps db))))
147
:spc (filter-statements-by-graph (gethash-if subject (gethash predicate (cache-index-ps db))))
148
:sp (map-list (gethash-if subject (gethash predicate (cache-index-ps db))))
149
:soc (filter-statements-by-object-by-graph (gethash subject (cache-index-s db)))
150
:so (filter-statements-by-object (gethash subject (cache-index-s db)))
151
:sc (filter-statements-by-graph (gethash subject (cache-index-s db)))
152
:s (map-list (gethash subject (cache-index-s db)))
153
:poc (filter-statements-by-graph (gethash-if object (gethash predicate (cache-index-po db))))
154
:po (map-list (gethash-if object (gethash predicate (cache-index-po db))))
155
:pc (filter-statements-by-graph (gethash predicate (cache-index-p db)))
156
:p (map-list (gethash predicate (cache-index-p db)))
157
:oc (filter-statements-by-graph (gethash object (cache-index-o db)))
158
:o (map-list (gethash object (cache-index-o db)))
159
:c (map-list (gethash graph (cache-index-c db)))
160
:all (map-index (cache-statements db))))))
162
(defun match-term-number-field (db graph subject predicate object continuation)
163
(de.setf.resource:map-statements* continuation db subject predicate object graph))
165
(defun count-term-number-field (db graph subject predicate object)
167
(flet ((count-continuation (context subjkect predicate object)
168
(declare (ignore context subjkect predicate object))
170
(declare (dynamic-extent #'count-continuation))
171
(de.setf.resource:map-statements* #'count-continuation db subject predicate object graph))
176
(defmethod compute-bgp-lambda ((repository term-number-field-cache) body &key
177
(base-dimensions ()) ; initial solution field variables
178
(projection-dimensions (expression-dimensions body))
179
(wildcard-term (repository-wildcard-term repository))
180
(default-context-term (repository-default-context-term repository))
181
(named-contexts-term (repository-named-contexts-term repository))
182
graph ; if in a graph clause, then either a variable or a literal
184
(graphs (cond ((null graph) (dataset-default-graphs dataset-graphs))
185
((variable-p graph) (dataset-named-graphs dataset-graphs))
186
((typep graph 'iri) (list graph))
188
(error "Invalid dataset specification: graph ~s, dataset ~s."
189
graph dataset-graphs))))
190
(variables (if (variable-p graph)
191
(cons graph (expression-variables body))
192
(expression-variables body)))
193
(dynamic-variables ())
194
(transaction (repository-transaction repository))
195
(trace *compute-bgp-lambda.trace*)
197
"Generate a matching operator from a BGP for the rdfcache store. The graph matching requirements are
198
described in graph.lisp. They are implemented with the following logic:
200
The graph argument is taken from the agp's graph field. If this bgp is in the scope of a graph clause, that
201
term noted by the macro-expansion for spocq.a:|graph|. Otherwise, it is an autonomous graph pattern, for
202
which there is no graph term. The default-graphs and named-graphs terms were either present in the context
203
query - as specified either in the rquest headers or in the request expression, or were present in the body
204
as spocq.a::|from| and spocq.a::|from-named| forms.
206
If the graph is a variable, the bgp applies to named graphs:
207
- if named-graphs is non-null, the match maps the variable over that set, while
208
- if named-graphs is null, no constraint is applied to the graph variable and it ranges query/next results.
209
If graph is a literal, a variable is introduced, bound to that value at the outset.
210
If graph is null, the bgp applies to 'default' graphs:
211
- If default-graphs is non-null, a variable is introduced and the match maps it over that set, while
212
- if default-graphs is null, a variable is introduced, bound to the repository's default graph designator.
214
The iteration operator propagates the accumulated bindings over a sequence of core single quad pattern
215
matches. Each of these starts with a query for which each term is either wild, or a foreign term which
216
either represents a constant value from the original bgp expression, or carries over a matched term from a
217
preceeding statement match. The process starts with initial bindings - the graph and/or a solution from an
218
initial field and augments the bindings as the matches proceed bin binding to the foreign pointers from
219
the successive matches as permitted by a given next.
221
This version evolved from the initial rdfcache interface primarily by removing all term structures.
222
As the term identifers are bout retrieved _and_ provided from the query constants, there is no need
223
to represent the terms' internal structure at the interface to the store. Which means none of the stack definitions
224
for the foreign objects and nothing to substitute in the patterns.
225
It also eliminates the (broken) mp code, also because it is not clear how to handle thread coordination in
226
a way which does not compromise rdfcache:next iteration rate."
227
(declare (ignore environment))
228
(when (assoc 'spocq.a:|quad| body)
229
(error "invalid bpg pattern: ~s" body))
230
;; use the dimensions provided in the call
231
;; (setf projection-dimensions (expression-dimensions body))
232
(let* ((named-graphs (dataset-named-graphs dataset-graphs))
233
(default-graphs (dataset-default-graphs dataset-graphs))
234
;; if the query had a literal graph term, provide a variable
235
(graph-variable (if (variable-p graph) graph 'graph))
236
;; note if the graph variable is among the initial solutions
237
(initial-solution-graph-variable (find graph base-dimensions))
238
;; indicate whether the graph needs to be set on first query
239
;; (set-graph-variable (and (variable-p graph) (not initial-solution-graph-variable)))
240
;; extract just the expressions wto be included in the matching and bindings propagation code
241
(iteration-patterns (remove-if-not #'bgp-pattern-form-p body))
242
(id (second (assoc 'spocq.a::|id| body)))
243
;; extract and consolidate anu declaration clauses
244
(declarations (reduce #'append (mapcar #'rest (remove 'spocq.a::|declare| body :test-not #'eq :key #'first))))
245
;; get the a-list of variables which were inferred to be related through a sameTerm filter constraint
246
;; in order to mirror any binding/setting
247
(equivalents (rest (assoc 'spocq.a::|equivalents| body)))
248
(triple-pattern-count (count 'spocq.a:|triple| iteration-patterns :key #'first))
249
(match-counters (loop for i from 0 below triple-pattern-count collect (gensym "COUNTER")))
250
(temp-match-counters match-counters)
251
(slice-offset (second (assoc 'spocq.a:|slice| body)))
252
(slice-count (third (assoc 'spocq.a:|slice| body)))
253
(projection-variable-count (length projection-dimensions))
254
(equivalent-variables (mapcar #'first equivalents))
255
(collection-variables (difference-dimensions projection-dimensions equivalent-variables))
256
(blank-nodes (expression-blank-nodes iteration-patterns))
257
(blank-node-map (loop for node in blank-nodes collect (cons node (cons-variable))))
258
(default-context-term-number (repository-object-term-number repository default-context-term))
259
(named-contexts-term-number (repository-object-term-number repository named-contexts-term)))
260
(declare (ignore declarations))
262
(labels ((intern-if-constant (object)
263
(cond ((variable-p object)
265
((spocq:blank-node-p object)
266
(or (rest (assoc object blank-node-map))
267
(error "lost a blank-node: ~a" object)))
268
((property-path-p object)
269
(repository-intern-property-path transaction object))
271
(rdfcache-object-term-number transaction object))))
272
(compute-filter-continuation (triples accumulated-variables)
273
(let* ((form (first triples))
274
(cc (compute-next-continuation (rest triples) accumulated-variables))
275
(test-expression (second form))
276
(test-variables (expression-variables test-expression))
277
(test-expression `(handler-case (ebv ,test-expression) (error () nil))))
279
(let ((test-aliases (loop for variable in test-variables collect (make-symbol (symbol-name variable)))))
280
`(when ((lambda ,test-aliases
281
(symbol-macrolet ,(loop for variable in test-variables
282
for alias in test-aliases
283
collect `(,variable (rdfcache-term-number-object ,transaction ,alias)))
284
(trace-bgp bgp.filter ',test-expression ',test-variables (list ,@test-aliases) (list ,@test-variables))
288
`(when ,test-expression ,cc))))
289
(compute-statement-continuation (triples accumulated-variables)
290
(let* ((form (first triples))
291
;; the first match must always use the graph term - either a constant from/from-named iri
292
;; or one of the wild-card, designators default/named/all.
293
;; if wild, then the result matters, but if constant, then the result does not.
294
;; all subsequent iterations use the result from the first match and do not need to rebind
295
(first-iteration-p (eq triples iteration-patterns))
296
(last-triple-p (null (assoc 'spocq.a:|triple| (rest triples))))
297
;; set the graph from each result for the outermost iteration only. that means:
298
;; trying w/o this: nb. in contrast to the term-pointer version, which sets the pointer
299
;; once only, the term-id based version must retrieve the id each iteration
300
(match-result-arguments (loop for term in (cons graph-variable (statement-terms form))
301
collect (cond ((or (not (variable-p term)) (member term accumulated-variables))
303
((and (eq term graph-variable)
304
(not first-iteration-p))
308
(uniqued-result-arguments (loop for vars on match-result-arguments
309
for v in match-result-arguments
310
collect (if (member v (rest vars))
313
(labels ((local-variable-p (v) (member v match-result-arguments))
314
(wild-variable-p (v) (and (local-variable-p v)
315
(not (eq v graph)))))
316
(let* ((match-pattern (loop for term in (cons graph-variable (statement-terms form))
317
collect (if (wild-variable-p term) wildcard-term term)))
318
(concrete-match-pattern (let ((graph-term (first match-pattern)))
319
(cons graph-term (loop for term in (rest match-pattern)
320
collect (if (eq term graph-term)
323
(accumulated-variables (append accumulated-variables (remove-if-not #'symbol-package match-result-arguments)))
324
(body (cond ((property-path-p (third match-pattern))
325
(error "Property paths are not supported for repository: ~s: ~s." repository (third match-pattern)))
327
((extension-operator-p (third match-pattern))
328
(error "Extension operators are not supported for repository: ~s: ~s." repository (third match-pattern)))
329
((or (member wildcard-term match-pattern)
331
(not (= default-context-term-number rdfcache:*default-context-number*)))
332
; if variables are in the statement pattern
333
; or the graph itself is a variable
334
; or the default graph comrpises the named graphs
335
; iterate over all matched bindings statement pattern
337
(let* ((path-continuation (gensym "MATCH-CONTINUATION"))
338
(ignored-variables (remove-if #'symbol-package uniqued-result-arguments))
339
(match-aliases (loop for v in match-result-arguments
340
for v-eq = (rassoc v equivalents)
343
and do (setf equivalents (remove v-eq equivalents))))
344
(continuation-form (compute-next-continuation (rest triples) accumulated-variables)))
346
;; constrain aliased variables
347
(unless (equal uniqued-result-arguments match-result-arguments)
348
(setf continuation-form
349
`(when (and ,@(loop for v in match-result-arguments
350
for u in uniqued-result-arguments
353
,continuation-form)))
355
(setf continuation-form
356
`(let ,(loop for (alias . v) in match-aliases
357
collect `(,alias ,v))
358
,continuation-form)))
359
`(flet ((,path-continuation (,@uniqued-result-arguments)
360
,@(when ignored-variables `((declare (ignorable ,@ignored-variables))))
361
(trace-bgp bgp.field-cache-matched ,@uniqued-result-arguments)
362
(unless (task-active-p *query*)
363
(log-debug "bgp premature completion: ~a" *query*)
364
(complete-solutions))
365
,(if (and slice-offset last-triple-p)
366
`(when (minusp (decf solution-offset))
369
(declare (dynamic-extent #',path-continuation))
370
(trace-bgp bgp.field-cache-to-match ',concrete-match-pattern)
371
(match-term-number-field ,repository ,@concrete-match-pattern #',path-continuation))))
374
(let ((continuation-form (compute-next-continuation (rest triples) accumulated-variables))
375
(count-form `(count-term-number-field ,repository ,@concrete-match-pattern)))
376
(unless (equal uniqued-result-arguments match-result-arguments)
377
(setf continuation-form
378
`(when (and ,@(loop for v in match-result-arguments
379
for u in uniqued-result-arguments
382
,continuation-form)))
383
(if (and slice-offset last-triple-p)
385
`(progn (incf match-requests)
386
(let ((count ,count-form))
387
(when (and (plusp count)
388
(not (plusp (decf solution-offset count))))
390
(incf ,(pop temp-match-counters))
391
,continuation-form)))
393
`(progn (incf match-requests)
394
(when (plusp ,count-form)
396
(incf ,(pop temp-match-counters))
397
,continuation-form))))))))
400
(compute-base-continuation ()
401
;; set the next solution row
402
(let ((collect-form `(collect-solution ,@collection-variables)))
405
(when (minusp (decf solution-count)) (complete-solutions))
409
(compute-next-continuation (triples accumulated-variables)
411
(let* ((form (first triples))) ; (triple ?s ?p ?o)
414
;; compule a triple/quad into a query/next continuation
415
(compute-statement-continuation triples accumulated-variables))
417
;; compile a filter into a constraint on the solutions which pass through it
418
(compute-filter-continuation triples accumulated-variables))))
419
(compute-base-continuation))))
421
(setf iteration-patterns (loop for (tag . spo) in iteration-patterns
424
(destructuring-bind (s p o) spo
425
`(,tag ,(intern-if-constant s)
426
,(if (extension-operator-p p)
428
(intern-if-constant p))
429
,(intern-if-constant o))))
430
(spocq.a:|filter| (cons tag spo)))))
431
(setf graphs (mapcar #'intern-if-constant graphs))
432
(setf default-graphs (mapcar #'intern-if-constant default-graphs))
433
(setf named-graphs (mapcar #'intern-if-constant named-graphs))
434
(setf equivalents (loop for (var . value-or-var) in equivalents collect (cons var (intern-if-constant value-or-var))))
436
;; allow for just the graph as a variable for literal bgp patterns?
437
(when (variable-p graph)
438
(setf projection-dimensions (union-dimensions (list graph) projection-dimensions)))
439
(let* (;; the interface operator accepts the repository, and optionally an initial spo solution field, and/or a graph sequence
440
;; this wraps an operator which iterates outer over the spo field to bind the starting values for those variables
441
;; for each pass and then iterates secondarily over the graph field to perform the pattern matches.
443
;; the top-level match form starts with all patterns, _no_ bound variables
444
;; corresponding to the patterns. not even the solution variables are bound initially, as they may themselves
445
;; start out as wild cards.
446
(base-bindings (if (or graphs (not graph))
447
(union-dimensions (list graph-variable) base-dimensions)
449
(initial-bindings (union-dimensions base-bindings dynamic-variables))
450
;; this cannot work in this way, as it causes all variables to
451
;; be handled as if they are pre-bound, with the consequence, that
452
;; they are matched, but never extractedd from the cursor...
453
;; (initial-bindings (union-dimensions base-bindings variables))
454
(triple-matching-form (compute-next-continuation iteration-patterns initial-bindings)))
457
(format *trace-output* "~&*compute-bgp-lambda.trace*~%body ~s~%graph ~s~%named ~s~%default ~s~%graphs ~s~%initial-solution-graph-variable ~s~%graph-variable ~s"
458
body graph named-graphs default-graphs graphs initial-solution-graph-variable graph-variable))
459
;; the actual query operator takes one of two forms. iff base dimensions are included, it is
460
;; generated to expect a solution field source, and to iterate the entire operator over the field's solutions.
461
;; without base dimensions, it runs autonomously.
462
;; the combination makes it possible to construct query processing both as reduction through bottom-up combination
463
;; and as solution combination, and even as some combination of the two
464
;; where evaluation materialized all intermediate solutions, it did not matter that the reduction order agree
465
;; with the matching order. the intermediate matching results were cached for delayed use as combination arguments.
466
;; where the solution data flows form one operator tot he next, with the intent to limit the space required for
467
;; intermediate fields by streaming results, the contradictory evaluation order would still require buffered
468
;; materialization. for example an expression of the form
470
;; (join (?a ?b ?c) (join (?b ?c) (?c)))
472
;; would reduce with data flow
474
;; ((?b ?c) . (?c) . (?a ?b ?c))
476
;; but match with data flow
477
;; (?c) -> (?b ?c) -> (?a ?b ?c)
479
;; which entail inverted match orders. the question is, how to enable both?
483
;; (put-field-page channel nil)
486
`(lambda (bgp-destination ,@(when base-dimensions '(source)))
487
(declare (optimize ,@*field-optimization*))
488
(assert-argument-types bgp-match
489
(bgp-destination (or channel function))
490
,@(when base-dimensions '((source (or channel function)))))
491
;; ,@(when base-dimensions `((print (cons source ',base-dimensions))))
492
(let* ((repository-id (repository-id *repository*))
493
(*thread-operations* (cons (list 'spocq.a:|bgp| ',body) *thread-operations*))
496
,@(when slice-offset `((solution-offset ,slice-offset)))
497
,@(when slice-count `((solution-count ,slice-count)))
499
(result-page-length (channel-page-length bgp-destination))
500
(result-index *field-page-length*)
503
(graph-ids-read (make-term-id-cache :single-thread t))
504
(*wildcard-identifier* ,wildcard-term)
505
(*default-context-identifier* ,default-context-term-number)
506
,@(loop for var in match-counters collect `(,var 0))
507
,@(loop for var in (intersection (set-difference dynamic-variables base-bindings) variables)
508
collect `(,var (query-binding-term-number ',var)))
509
;; this allows to specify dynamic variables retrospectively, but suppresses
510
;; extracting them from the cursor
512
,@(loop for var in (set-difference variables base-bindings)
513
collect `(,var (query-binding-term-number ',var))))
514
(declare (ignorable repository-id)) ; if just paths
516
(labels ((coerce-to-term-id (term-number)
517
(typecase term-number
519
(t (log-warn "bgp match result not a term number: ~s." term-number)
521
(collect-solution ,collection-variables
522
(trace-bgp bgp-match.collect-solution ,@collection-variables)
524
,(if projection-dimensions
525
`(let ,(loop for (alias . equivalent) in equivalents ; bind left-over constants
526
collect (list alias equivalent))
527
(next-solution-location)
528
(locally (declare (type (simple-array fixnum (* ,projection-variable-count)) result-page)
529
(type fixnum result-index)
530
(ftype (function (t) fixnum) coerce-to-term-id)
531
(optimize ,@*field-optimization*))
532
(setf ,@(loop for var-index from 0
533
for variable in projection-dimensions
534
nconc `((aref result-page result-index ,var-index)
535
(coerce-to-term-id ,variable))))))
536
'(next-solution-location)))
537
(next-solution-location ()
538
;; return a page (possible newly created) and the next free location in that page
539
(when (>= (incf result-index) result-page-length)
540
(when result-page (put-result result-page))
541
(setf result-page (new-field-page bgp-destination result-page-length ,projection-variable-count)
543
(values result-page result-index))
544
(complete-solutions ()
545
(trace-bgp bgp-match.complete-solutions result-count)
546
(incf *match-requests* match-requests)
547
(incf *match-responses* match-results)
548
(log-debug "bgp matches+counts: ~s: requests: ~s, matches: (~s ~s), solutions: ~s"
549
repository-id match-requests match-results (list ,@match-counters) result-count)
551
(let ((page-result-count (1+ result-index)))
552
(when (< page-result-count result-page-length)
554
(adjust-page result-page (list page-result-count ,projection-variable-count)))))
555
(put-result result-page))
556
(complete-field bgp-destination)
557
;; (print (list :bgp result-count :complete))
558
(incf-stat *solutions-constructed* result-count)
559
(return-from :bgp-match result-count))
561
(trace-bgp bgp-match.enqueue bgp-destination ',projection-dimensions page)
562
(put-field-page bgp-destination page)
563
(unless (task-active-p *query*)
564
(complete-field bgp-destination)
565
(return-from :bgp-match result-count))))
566
(trace-bgp bgp.start ',id (task-id *query*)
567
repository-id ',projection-dimensions)
568
(incf-stat *algebra-operations*)
569
;; (print (list :in-bgp repository repository-id))
570
;; unless there are paths present (actually zero-length paths is the issue)
571
;; require an id to perform the query. otherwise there can be no result - skip it
573
(progn ,(let ((iterate-over-graphs `(flet ((match-patterns (,graph-variable)
574
;; if the graph is to be matched, it is rebound in the matching form
575
;; (declare (ignorable ,graph-variable))
576
(when (and ,graph-variable
577
(not (eql ,graph-variable last-graph-id)))
578
(setf last-graph-id ,graph-variable)
579
(setf (gethash ,graph-variable graph-ids-read) t))
580
,triple-matching-form))
582
;; if the dataset was specified, use it and respect any initial solution constraint
583
(if initial-solution-graph-variable
584
`(progn ,@(loop for graph in graphs
585
collect `(cond ((eql ,wildcard-term initial-solution-graph-variable)
586
(match-patterns ,graph))
587
((spocq.e:equal ,initial-solution-graph-variable ,graph)
588
(return (match-patterns ,graph))))))
589
`(progn ,@(loop for graph in graphs
590
collect `(match-patterns ,graph)))))
592
;; if in a graph clause, if there was no dataset declared,
593
;; either use an initial soution binding or search.
594
;; otherwise, the effective dataset includes no named graph
595
;; see rdf-sparql-query 8.2.1
596
(if initial-solution-graph-variable
597
`(match-patterns ,graph)
600
`(match-patterns ,named-contexts-term-number))))
602
;; outside of a graph clause, the analogous applies
603
;; if there is no dataset clause, use the default graph.
604
;; otherwise the default graph is empty.
607
`(match-patterns ,default-context-term-number)))))))
609
`(do-pages (page source)
610
,(let ((macros (loop for variable in base-dimensions
612
collect `(,variable (aref page page-index ,i)))))
613
`(locally (declare (type (simple-array fixnum (* ,(length base-dimensions))) page)
614
(optimize ,@*field-optimization*))
615
(assert (and (typep page '(simple-array fixnum))
616
(= (array-dimension page 1) ,(length base-dimensions)))
618
"Invalid propagated page: ~s" page)
619
(trace-data bgp-match.dequeue bgp-destination ',base-dimensions page (term-value-field page))
620
;; (let ((*print-array* nil)) (print page))
621
(loop for page-index from 0 below (array-dimension page 0)
622
do (symbol-macrolet ,macros
623
;; (print (list page-index ,@(loop for variable in base-dimensions append (list (list 'quote variable) variable))))
624
,iterate-over-graphs)))))
625
iterate-over-graphs))
626
(complete-solutions))))
627
(log-warn "incomplete bgp: ~s." ',id)
629
(log-debug "query [~a] bgp [~a] lambda: ~s"
630
(task-id *query*) id query-lambda)