Coverage report: /development/source/library/org/datagraph/spocq-shard/src/store/rlmdb/quad.lisp
| Kind | Covered | All | % |
| expression | 126 | 486 | 25.9 |
| branch | 14 | 44 | 31.8 |
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.rdf.lmdb.implementation)
5
(:documentation "LMDB rdf quad operations."
6
"A QUAD object comprises a (graph x subject x predicate x object) combination,
7
where each element is an (unsigned byte 32) term index.
8
These are stored as the index keys in the various s-p-o-g combination indices.
9
A retrieval involves two principle quad-related operations
10
- permute a quad pattern for use as an index key
11
- test (the permuted) pattern against the keys yields by a cursor scan to constrain results.
12
see dydra-cgi:src;dydra;quad.h
14
bool match(const quad& other) const {
16
if (context_id() == -2) { // HACK for named-graph iteration
17
if (other.context_id() == -1) {
23
if (context_id() != 0 && context_id() != other.context_id()) {
27
if (subject_id() != 0 && subject_id() != other.subject_id()) {
31
if (predicate_id() != 0 && predicate_id() != other.predicate_id()) {
35
if (object_id() != 0 && object_id() != other.object_id()) {
36
// TODO: xsd:integer and xsd:decimal rules.
45
;;; (quad-pattern-mask-index #(43851499 0 438 0))
46
;;; (quad-pattern-key-map-index #(43851499 0 438 0))
48
(defun quad-match-p (test-quad pattern-quad)
49
(and (case (spocq:quad-graph pattern-quad)
50
(-2 (/= -1 (spocq:quad-graph test-quad)))
52
(t (spocq.e:= (spocq:quad-graph pattern-quad) (spocq:quad-graph test-quad))))
53
(or (= 0 (spocq:quad-subject pattern-quad))
54
(spocq.e:= (spocq:quad-subject pattern-quad) (spocq:quad-subject test-quad)))
55
(or (= 0 (spocq:quad-predicate pattern-quad))
56
(spocq.e:= (spocq:quad-predicate pattern-quad) (spocq:quad-predicate test-quad)))
57
(or (= 0 (spocq:quad-object pattern-quad))
58
(spocq.e:= (spocq:quad-object pattern-quad) (spocq:quad-object test-quad)))))
61
(defun %quad-match-p (%pattern-quad %test-quad)
62
(declare (optimize (speed 3) (safety 0)))
64
(format *trace-output* "~%%quad-match-p: pattern: (~s ~s ~s ~s) instance: (~s ~s ~s ~s)"
65
(%quad-context %pattern-quad) (%quad-subject %pattern-quad) (%quad-predicate %pattern-quad) (%quad-object %pattern-quad)
66
(%quad-context %test-quad) (%quad-subject %test-quad) (%quad-predicate %test-quad) (%quad-object %test-quad))
67
(assert (and (cffi-sys:pointerp %pattern-quad) (cffi-sys:pointerp %test-quad)) ()
68
"%quad-match-p: pointers are required.")
69
(and (or (= 0 (%quad-context %pattern-quad))
70
(= (%quad-context %pattern-quad) (%quad-context %test-quad)))
71
(or (= 0 (%quad-subject %pattern-quad))
72
(= (%quad-subject %pattern-quad) (%quad-subject %test-quad)))
73
(or (= 0 (%quad-predicate %pattern-quad))
74
(= (%quad-predicate %pattern-quad) (%quad-predicate %test-quad)))
75
(or (= 0 (%quad-object %pattern-quad))
76
(= (%quad-object %pattern-quad) (%quad-object %test-quad)))))
78
(defun term-number-record-to-quad (%quad quad)
79
(setf (spocq:quad-subject quad)
80
(rlmdb:term-number-value (cffi:foreign-slot-value %quad '(:struct quad) 'subject))
81
(spocq:quad-predicate quad)
82
(rlmdb:term-number-value (cffi:foreign-slot-value %quad '(:struct quad) 'predicate))
83
(spocq:quad-object quad)
84
(rlmdb:term-number-value (cffi:foreign-slot-value %quad '(:struct quad) 'object))
85
(spocq:quad-graph quad)
86
(rlmdb:term-number-value (cffi:foreign-slot-value %quad '(:struct quad) 'context)))
89
(defun term-number-record-to-vector (%quad vector)
91
(cffi:foreign-slot-value %quad '(:struct quad) 'subject)
93
(cffi:foreign-slot-value %quad '(:struct quad) 'predicate)
95
(cffi:foreign-slot-value %quad '(:struct quad) 'object)
97
(cffi:foreign-slot-value %quad '(:struct quad) 'context))
102
(defgeneric quad-to-term-number-key (quad %quad transform)
104
"Where the index databases vary effect sort order with a constant predicate
105
by varing the term order, this reconstructs a quad as per the sort order map.
106
This applies to quad indices in the rdfcache quad indix databases only.")
107
(:method ((quad spocq:quad) %quad transform)
108
;; quad transform map indicates the respective source index
109
(flet ((get-indexed-quad-slot-term-number (index)
110
(spocq.i::rdfcache-lookup-object-term-number
112
(0 (spocq:quad-graph quad))
113
(1 (spocq:quad-subject quad))
114
(2 (spocq:quad-predicate quad))
115
(3 (spocq:quad-object quad))))))
116
;;(print (list :transform transform))
118
;;(print (list x :from (aref transform x) :is (get-indexed-quad-slot-term-number (aref transform x))))
119
(setf (cffi:mem-aref %quad 'term-id x)
120
(get-indexed-quad-slot-term-number (aref transform x)))))
121
;;(print :term-number.key)
123
;;(%print-quad %quad *trace-output*)
125
(:method ((quad vector) %quad transform)
126
(flet ((coerce-term-number (tn)
127
(cond ((= tn -1) #xffffffff)
130
(setf (cffi:mem-aref %quad 'term-id 0)
131
(coerce-term-number (aref quad (aref transform 0))))
132
(setf (cffi:mem-aref %quad 'term-id 1)
133
(coerce-term-number (aref quad (aref transform 1))))
134
(setf (cffi:mem-aref %quad 'term-id 2)
135
(coerce-term-number (aref quad (aref transform 2))))
136
(setf (cffi:mem-aref %quad 'term-id 3)
137
(coerce-term-number (aref quad (aref transform 3)))))
138
;; (print :term-number.key *trace-output*)
139
;; (print quad *trace-output*)
140
;; (%print-quad %quad *trace-output*)
144
(defgeneric quad-to-quad-record (quad %quad)
145
(:documentation "pack the respective term numbers into the quad record.
146
if some term is not present, return nil")
147
(:method ((quad spocq:quad) (quad-vector vector))
148
(flet ((term-number-or-wild (object)
150
(or (spocq.i::rdfcache-lookup-object-term-number object)
151
(return-from quad-to-quad-record nil))
153
(setf (aref quad-vector 0) (term-number-or-wild (spocq:quad-graph quad)))
154
(setf (aref quad-vector 1) (term-number-or-wild (spocq:quad-subject quad)))
155
(setf (aref quad-vector 2) (term-number-or-wild (spocq:quad-predicate quad)))
156
(setf (aref quad-vector 3) (term-number-or-wild (spocq:quad-object quad)))
158
(:method ((quad spocq:quad) %quad)
159
(flet ((term-number-or-wild (object)
161
(or (spocq.i::rdfcache-lookup-object-term-number object)
162
(return-from quad-to-quad-record nil))
164
(setf (%quad-context %quad) (term-number-or-wild (spocq:quad-graph quad)))
165
(setf (%quad-subject %quad) (term-number-or-wild (spocq:quad-subject quad)))
166
(setf (%quad-predicate %quad) (term-number-or-wild (spocq:quad-predicate quad)))
167
(setf (%quad-object %quad) (term-number-or-wild (spocq:quad-object quad)))
169
(:method ((quad vector) %quad)
170
(flet ((coerce-term-number (tn)
171
(cond ((= tn -1) #xffffffff)
174
(setf (%quad-context %quad) (coerce-term-number (aref quad 0)))
175
(setf (%quad-subject %quad) (coerce-term-number (aref quad 1)))
176
(setf (%quad-predicate %quad) (coerce-term-number (aref quad 2)))
177
(setf (%quad-object %quad) (coerce-term-number (aref quad 3)))
179
#+(or) ;; SHOULD RETURN NIL, NOT SIGNAL AN ERROR
180
(cffi:with-foreign-objects ((%quad-pattern '(:struct rdfcache::quad)))
181
(quad-to-term-number-record
182
(spocq:make-quad :subject "one" :predicate "two" :object "three" :graph "for.")
185
(defgeneric quad-to-tsiquad-record (quad %tsiquad)
186
(:method ((quad spocq:quad) %tsiquad)
187
;; tquad transform map indicates the respective source index
188
(flet ((term-number-or-wild (object)
190
(or (spocq.i::rdfcache-lookup-object-term-number object)
191
(return-from quad-to-tsiquad-record nil))
193
(setf (%tsiquad-context %tsiquad) (term-number-or-wild (spocq:quad-graph quad)))
194
(setf (%tsiquad-subject %tsiquad) (term-number-or-wild (spocq:quad-subject quad)))
195
(setf (%tsiquad-predicate %tsiquad) (term-number-or-wild (spocq:quad-predicate quad)))
196
(setf (%tsiquad-object %tsiquad) (term-number-or-wild (spocq:quad-object quad)))
198
(:method ((quad vector) %tsiquad)
199
(flet ((coerce-term-number (tn)
200
(cond ((= tn -1) #xffffffff)
203
(setf (%tsiquad-context %tsiquad) (coerce-term-number (aref quad 0)))
204
(setf (%tsiquad-subject %tsiquad) (coerce-term-number (aref quad 1)))
205
(setf (%tsiquad-predicate %tsiquad) (coerce-term-number (aref quad 2)))
206
(setf (%tsiquad-object %tsiquad) (coerce-term-number (aref quad 3)))
207
;; (print :term-number.key *trace-output*)
208
;; (print quad *trace-output*)
209
;; (%print-quad %quad *trace-output*)
212
(defgeneric quad-to-tsoquad-record (quad %tsoquad)
213
(:method ((quad spocq:quad) %tsoquad)
214
;; tsoquad transform map indicates the respective source index
215
(flet ((term-number-or-wild (object)
217
(or (spocq.i::rdfcache-lookup-object-term-number object)
218
(return-from quad-to-tsoquad-record nil))
220
(setf (%tsoquad-context %tsoquad) (term-number-or-wild (spocq:quad-graph quad)))
221
(setf (%tsoquad-subject %tsoquad) (term-number-or-wild (spocq:quad-subject quad)))
222
(setf (%tsoquad-predicate %tsoquad) (term-number-or-wild (spocq:quad-predicate quad)))
223
(setf (%tsoquad-object %tsoquad) (term-number-or-wild (spocq:quad-object quad)))
225
(:method ((quad vector) %tsoquad)
226
(flet ((coerce-term-number (tn)
227
(cond ((= tn -1) #xffffffff)
230
(setf (%tsoquad-context %tsoquad) (coerce-term-number (aref quad 0)))
231
(setf (%tsoquad-subject %tsoquad) (coerce-term-number (aref quad 1)))
232
(setf (%tsoquad-predicate %tsoquad) (coerce-term-number (aref quad 2)))
233
(setf (%tsoquad-object %tsoquad) (coerce-term-number (aref quad 3)))
236
(defgeneric quad-to-tstquad-record (quad %tstquad)
237
(:method ((quad spocq:quad) %tstquad)
238
;; tstquad transform map indicates the respective source index
239
(flet ((term-number-or-wild (object)
241
(or (spocq.i::rdfcache-lookup-object-term-number object)
242
(return-from quad-to-tstquad-record nil))
244
(setf (%tstquad-context %tstquad) (term-number-or-wild (spocq:quad-graph quad)))
245
(setf (%tstquad-subject %tstquad) (term-number-or-wild (spocq:quad-subject quad)))
246
(setf (%tstquad-predicate %tstquad) (term-number-or-wild (spocq:quad-predicate quad)))
247
(setf (%tstquad-object %tstquad) (term-number-or-wild (spocq:quad-object quad)))
249
(:method ((quad vector) %tstquad)
250
(flet ((coerce-term-number (tn)
251
(cond ((= tn -1) #xffffffff)
254
(setf (%tstquad-context %tstquad) (coerce-term-number (aref quad 0)))
255
(setf (%tstquad-subject %tstquad) (coerce-term-number (aref quad 1)))
256
(setf (%tstquad-predicate %tstquad) (coerce-term-number (aref quad 2)))
257
(setf (%tstquad-object %tstquad) (coerce-term-number (aref quad 3)))
258
;; (print :term-number.key *trace-output*)
259
;; (print quad *trace-output*)
260
;; (%print-quad %quad *trace-output*)
263
(defun quad-to-tquad-record (quad %tquad)
264
"implemented the same as -to-tstquad"
265
(quad-to-tstquad-record quad %tquad))
267
(defun term-number-key-to-term-number-quad (%key %quad transform)
268
;(print (list :term-number-key-to-term-number-quad transform) *trace-output*)
269
(setf (cffi:mem-aref %quad 'term-id (aref transform 0)) (cffi:mem-aref %key 'term-id 0))
270
(setf (cffi:mem-aref %quad 'term-id (aref transform 1)) (cffi:mem-aref %key 'term-id 1))
271
(setf (cffi:mem-aref %quad 'term-id (aref transform 2)) (cffi:mem-aref %key 'term-id 2))
272
;(print (list (cffi:mem-aref %key 'term-id 2) (cffi:mem-aref %quad 'term-id (aref transform 2))))
273
(setf (cffi:mem-aref %quad 'term-id (aref transform 3)) (cffi:mem-aref %key 'term-id 3))
274
#|(format *trace-output* "~&[~s](~s ~s ~s ~s)~%"
276
(cffi:mem-aref %key 'term-id 0) (cffi:mem-aref %key 'term-id 1) (cffi:mem-aref %key 'term-id 2) (cffi:mem-aref %key 'term-id 3))
277
(%print-quad %key *trace-output*)
278
(%print-quad %quad *trace-output*)|#
283
(cffi:with-foreign-object (%quad '(:struct rdfcache::quad))
284
(%print-quad %quad *trace-output*)
285
(dotimes (x 4) (setf (cffi:mem-aref %quad 'term-id x) x))
286
(%print-quad %quad *trace-output*)
289
(defun copy-quad-record (from to &optional (offset 0))
291
;;(%print-quad from *trace-output*)
292
;;(%print-quad to *trace-output*)
293
(loop for i below 4 for j from offset
294
do (setf (cffi:mem-aref to 'term-id j) (cffi:mem-aref from 'term-id i)))
295
;;(setf (%quad-subject to) (%quad-subject from))
296
;;(setf (%quad-predicate to) (%quad-predicate from))
297
;;(setf (%quad-object to) (%quad-object from))
298
;;(setf (%quad-context to) (%quad-context from))
299
;;(%print-quad from *trace-output*)
300
;;(%print-quad to *trace-output*)
303
(defgeneric copy-quad-pattern (from)
304
(:method ((from spocq:quad))
305
(spocq.i::copy-quad from))
306
(:method ((from vector))
307
(make-array 4 :initial-contents from)))
309
(defgeneric copy-tquad-pattern (from)
310
(:method ((from spocq:quad))
311
(spocq.i::copy-tquad from))
312
(:method ((from vector))
313
(make-array 5 :initial-contents from)))
315
(defun wild-term-p (term)
316
(or (null term) (eql term 0)))
319
;;; (trace test-visibility)
320
;;; (loop for ordinal below 10 collect (test-visibility ordinal #(1 3 5 7) 4))
322
(cffi:defcallback %compare-keys :int ((lhs :pointer) (rhs :pointer))
323
(%compare-lmdb-keys lhs rhs))
325
(defun %compare-lmdb-keys (lhs rhs)
326
(declare (type SB-SYS:SYSTEM-AREA-POINTER lhs rhs)
327
(optimize (speed 3) (safety 0) (space 3)))
329
(assert (= 16 (cffi:pointer-address (cffi:foreign-slot-value lhs '(:struct liblmdb:val) 'liblmdb:mv-size)))
331
"key size is invalid: ~s" (cffi:pointer-address (cffi:foreign-slot-value lhs '(:struct liblmdb:val) 'liblmdb:mv-size)))
332
(assert (= 16 (cffi:pointer-address (cffi:foreign-slot-value rhs '(:struct liblmdb:val) 'liblmdb:mv-size)))
334
"key size is invalid: ~s" (cffi:pointer-address (cffi:foreign-slot-value rhs '(:struct liblmdb:val) 'liblmdb:mv-size)))
336
(let ((lhs-quad (cffi:foreign-slot-value lhs '(:struct liblmdb:val) 'liblmdb:mv-data))
337
(rhs-quad (cffi:foreign-slot-value rhs '(:struct liblmdb:val) 'liblmdb:mv-data)))
338
(declare (dynamic-extent lhs-quad rhs-quad))
339
(%compare-quad lhs-quad rhs-quad))
343
(declaim (type (function (SB-SYS:SYSTEM-AREA-POINTER SB-SYS:SYSTEM-AREA-POINTER) fixnum) %compare-quad))
345
(defun %compare-quad (lhs rhs)
346
(declare (dynamic-extent lhs rhs)
347
(optimize (speed 3) (safety 0)))
350
(print :%compare-quad *trace-output*)
351
(%print-quad lhs *trace-output*)
352
(%print-quad rhs *trace-output*))
356
for lhs_i = (cffi:mem-aref lhs 'term-id i)
357
for rhs_i = (cffi:mem-aref rhs 'term-id i)
362
finally (return 0))))
364
(defun %quad-less-p (lhs rhs)
365
(eql (%compare-quad lhs rhs) -1))
367
(defun compare-quad (lhs rhs)
370
(flet ((cmp-term (lhst rhst)
371
(let ((sign (signum (- lhst rhst))))
373
(return-from compare-quad sign)))))
374
(map nil #'cmp-term lhs rhs)
376
;;; (compare-quad #(0 0 0 0) #(0 0 0 0))
381
(macrolet ((def-compare-tquad (name order)
382
(let* ((name (cons-symbol *package* 'compare-tquad- name))
383
(%name (cons-symbol *package* '% name))
384
(fields #(context subject predicate time))
385
(clauses (loop for i below 4
386
for accessor = (cons-symbol *package* '%tquad- (aref fields i))
387
collect `(let ((sign (signum (- (,accessor lhs) (,accessor rhs)))))
389
(return-from ,name sign))))))
390
`(progn (defun ,name (lhs rhs)
391
,@(loop for ref across order
392
collect (nth ref clauses))
394
(cffi:defcallback ,%name :int ((lhs :pointer) (rhs :pointer))
396
(def-compare-tquad gspt #(0 1 2 3))
397
(def-compare-tquad gpts #(0 2 3 1))
398
(def-compare-tquad gtsp #(0 3 1 2))
399
(def-compare-tquad sptg #(1 2 3 0))
400
(def-compare-tquad ptsg #(2 3 1 0))
401
(def-compare-tquad tspg #(3 1 2 0)))