Coverage report: /development/source/library/org/datagraph/spocq-shard/src/store/rlmdb/repository-collation.lisp
| Kind | Covered | All | % |
| expression | 138 | 174 | 79.3 |
| branch | 12 | 16 | 75.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.rdf.lmdb.implementation; -*-
3
(in-package :org.datagraph.rdf.lmdb.implementation)
5
(:documentation "LMDB repository multi-revision collation"
6
"This serves BGP processing where the statements constitute a 'star' pattern,
7
in which case, the solutions are extended with bindings for all respective
8
predicates by scanning them as a single pass.
10
This operator, rlmdb:collate-repository-statements, provides an interface
11
analogous to that of rlmdb:map-repository-statements, but instead of
12
passing a single statement pattern, it passes a vector which combines just
13
just graph and subject terms with the predicate set to be collated.
15
In order that the behaviour of other arguments should carry over in order to
19
the operator is implemented by delegating to the implementation for the
20
respective s.g.p.o operator, collecting the intermediate results for all
21
predicates and object results for a given s.g combination and emitting those as
22
the collated solutions.
23
(see rlmdb:map-repository-statements)
26
;;; map over indices which index event identifiers in the respective value domain.
27
;;; these can be scanned so as to emit result in event order and, for some pattern combinations
28
;;; collate multi-statement patterns into solutions in-line, without joining,
30
(defgeneric rlmdb::collate-repository-statements (operator repository collation-pattern
36
"Given a collation pattern, use the s.g.p.o index to, the index to extract the solution
37
for the given predicates in-line.
38
Delegate to index's map method with an intermediate continuation to collate solutions.")
40
(:method (operator (repository rlmdb:repository) (pattern t) &rest args)
41
"The base method for a repository just returns nil to indicate no index applied"
42
(declare (ignore args))
45
(:method (operator (id string) (pattern t) &rest args)
46
"given a string operate on the dydra repository"
47
(declare (dynamic-extent args))
48
(apply #'rlmdb::collate-repository-statements operator (spocq.i:repository id) pattern args))
50
(:method (operator (transaction spocq.i::lmdb-transaction) (pattern t)
52
"Given an api transaction, delegate to its revision"
53
(apply #'rlmdb::collate-repository-statements operator (spocq.i::transaction-revision transaction)
57
(:method (operator (revision spocq.i::lmdb-revision) (pattern t)
59
&key revision-predicate domain-predicate term-precedence
61
"Given an api revision, capture its ordinal bounds use them to operate on the storage"
62
(declare (ignore domain-predicate term-precedence))
63
(apply #'rlmdb::collate-repository-statements operator (repository-lmdb-repository revision)
65
:revision-predicate (or revision-predicate
66
(compute-revision-predicate (list :first (spocq.i::revision-min-revision-ordinal revision)
67
:last (spocq.i::revision-max-revision-ordinal revision))))
70
(:method (operator (repository spocq.i::lmdb-repository) (pattern t) &rest args)
71
"Given an api repository, delegate to its storage"
72
(declare (dynamic-extent args))
73
(apply #'rlmdb::collate-repository-statements operator (repository-lmdb-repository repository)
77
(:method :around (operator (repository rlmdb:repository) (pattern t) &rest args)
78
"For any storage repository, establish a transaction context and continue with the
79
methods applicable to its storage variant."
80
(declare (ignore args))
81
(if (and lmdb:*transaction*
82
(eq (lmdb:transaction-environment lmdb:*transaction*) repository))
84
(lmdb:with-transaction ((transaction (lmdb:make-transaction repository :flags liblmdb:+rdonly+))
85
:initial-disposition :begin :normal-disposition :abort
86
:error-disposition :abort)
89
;; the only valid pattern is a vector of the form #(s g . p*).
90
;; match the pattern abstracted over predicates and collate g/s/p/e
91
(:method (operator (repository rlmdb::repository) (collation-pattern vector) &rest args)
92
(declare (dynamic-extent args))
93
(let* ((key-pattern (vector (aref collation-pattern 0) (aref collation-pattern 1) 0 0))
94
(index-database (repository-quad-pattern-index repository key-pattern)))
95
(apply #'rlmdb::collate-index-statements
97
index-database collation-pattern args)))
99
;; other repository types should not get here
100
(:method ((operator t) (repository rlmdb::repository) quad-pattern &rest args)
101
(log-warn "rlmdb:map-repository-events: invoked without event indices: ~s ~s ~s"
102
repository quad-pattern args)
107
(defmethod rlmdb::collate-index-statements (continuation (index-database rlmdb::index-database) collation-pattern &rest args)
108
"Map and correlate with g.s as the dominant order."
111
(solution-vector (make-array (length collation-pattern) :initial-element 0))
112
(solution-field (make-array (length collation-pattern)))
113
(quad-pattern (make-array 4 :initial-element 0))
115
(setf (aref quad-pattern 0) (aref collation-pattern 0))
116
(setf (aref quad-pattern 1) (aref collation-pattern 1))
117
(loop for i from 2 below (length solution-field)
118
do (setf (aref solution-field i) (make-array 10 :fill-pointer 0 :adjustable t)))
119
(labels ((collate-statement (%quad)
120
;; (%print-quad %quad *trace-output*)
121
;; accept each matched quad, constraint to those predicates in the collation pattern,
123
(let ((next-context (spocq.i::%quad-context %quad))
124
(next-subject (spocq.i::%quad-subject %quad))
125
(predicate-index (position (spocq.i::%quad-predicate %quad) collation-pattern :start 2))
126
(next-object (spocq.i::%quad-object %quad)))
127
;; (print (list next-context next-subject predicate-index next-object))
128
(cond (predicate-index
130
(unless (and (= subject next-subject)
131
(= context next-context))
132
;;(print (list :continued solution-vector))
134
(setf subject next-subject
135
context next-context)
136
(vector-push-extend next-object (aref solution-field predicate-index)))
140
(if (< i (length solution-field))
141
(let ((predicate-objects (aref solution-field i)))
142
(loop for next-value across predicate-objects
144
(setf (aref solution-vector i) next-value)
145
(emit-predicate (1+ i)))))
146
(funcall continuation solution-vector)))
148
;; (print (list :es solution-field))
149
(when (loop for i from 2 below (length solution-field)
150
when (zerop (length (aref solution-field i)))
153
(setf (aref solution-vector 0) context
154
(aref solution-vector 1) subject)
156
(loop for i from 2 below (length solution-field)
157
do (setf (fill-pointer (aref solution-field i)) 0)))
159
(declare (dynamic-extent #'collate-statement))
160
(multiple-value-prog1 (apply #'rlmdb::map-index-statements #'collate-statement index-database quad-pattern args)
161
(unless (= subject 0)
162
(emit-solutions))))))
166
;;; map over specific term positions
167
;;; context, subject, predicate or object, whereby the triple positions permit a qualifying context
168
;;; all use the spog index, as it is not shuffeled and then pick the term from the respective position