Coverage report: /development/source/library/org/datagraph/spocq-shard/src/core/encoding/sparql-results-nquads.lisp

KindCoveredAll%
expression107269 39.8
branch1026 38.5
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; -*-
2
 
3
 (in-package :org.datagraph.spocq.implementation)
4
 
5
 ;;; results as nquads; serializer only
6
 
7
 (defparameter *ntriples-unbound-term-mode* 'spocq:unbound-variable) ;; 'error)
8
 (defparameter *nquads-default-graph-term* nil) ; |urn:dydra|:|default|)
9
 
10
 
11
 ;;; writing sparql results and terms
12
 
13
 (defun nquads-eol (stream)
14
   (write-string (load-time-value (coerce #(#\return #\linefeed) 'string)) stream))
15
 
16
 (defgeneric write-rdf-nquads (results stream)
17
   (:documentation "Encode the result field to the stream as ntriples.
18
  The results must have three or four dimensions - if four, then treat the elemnents as quads.
19
  Allow the first element to be a list of dimensions.
20
  The remaining entries aer solutions sets. if a variable is unbound, the solution element is etf:nil.")
21
   
22
   (:method ((results list-solution-field) (stream stream))
23
     (write-rdf-nquads (cons (solution-field-dimensions results)
24
                             (solution-field-solutions results))
25
                       stream))
26
 
27
   (:method ((results cons) (stream stream))
28
     (let* ((variables (if (every #'variable-p (first results))
29
                         (first results)))
30
            (solutions (if (eq variables (first results)) (rest results) results))
31
            (index 0)
32
            (start (or (response-offset) 0))
33
            (end (response-end))
34
            (default-graph-term (iri-lexical-form *nquads-default-graph-term*)))
35
       (if variables
36
         (unless (typep (length variables) '(integer 3 4))
37
           (spocq.e:request-error "Invalid n-triples/n-quads field: ~s ..." variables))
38
         (setf variables
39
               (case (length (first solutions))
40
                 (4 (quad-dimensions))
41
                 (t (triple-dimensions)))))
42
       (when (plusp start)
43
         (setf solutions (nthcdr start solutions))
44
         (if end
45
           (decf end start)))
46
       (dolist (result solutions)
47
         (when (and end (>= index end))
48
           (return))
49
         (loop for value in result
50
               for value-index from 0
51
               do (typecase value
52
                    ;; emit non-null values and enable commas
53
                    ((or null spocq:unbound-variable (member etf:nil))
54
                     (if (= value-index 3)
55
                       (when default-graph-term
56
                         (write-string default-graph-term stream))
57
                       (ecase *ntriples-unbound-term-mode*
58
                         (spocq:unbound-variable
59
                          (format stream "<urn:dydra:unbound~@[:~a~]>" (nth value-index variables)))
60
                         (error
61
                          (spocq.e:request-error "invalid null ntriples/nquads term: ~s" value)))))
62
                    (t (encode-turtle-object value stream)
63
                       (write-char #\space stream))))
64
         (write-char #\. stream)
65
         (incf index)
66
         (nquads-eol stream))
67
       (incf-stat *statements-returned* index)
68
       index))
69
   
70
   (:method ((results solution-generator) (stream stream))
71
     (let* ((dimensions (solution-generator-dimensions results))
72
            (channel (solution-generator-channel results))
73
            (base-width (length dimensions))
74
            (index 0)
75
            (start (or (response-offset) 0))
76
            (end (response-end)))
77
       (case (length dimensions)
78
         (0 ) ; unit table
79
         ((3 4)
80
          (do-pages (page channel)
81
                    (when (and end (>= index end))
82
                      (return))
83
                    (if (>= (+ index (array-dimension page 0)) start)
84
                        (cond ((= base-width (array-dimension page 1))
85
                               (trace-data write-rdf-ntriples dimensions (term-value-field page))
86
                               (setf index (write-rdf-field-nquads page dimensions stream index start end)))
87
                              (t
88
                               (log-warn "field width mismatch: ~s : ~s."
89
                                         dimensions (array-dimension page 1))
90
                               (incf index (array-dimension page 0))))
91
                        ; otherwise skip the entire page
92
                        (incf index (array-dimension page 0))))
93
          (incf-stat *statements-returned* index))
94
         (t
95
          ;; this should not happen, as other arity should not parse
96
          (spocq.e:request-error "Invalid ntriples/nquads field: ~s ..." dimensions)))
97
       index)))
98
 
99
 (defun write-rdf-field-nquads (page variables stream &optional (index 0) (start 0) end)
100
   (assert (= (length (array-dimensions page)) 2) () "invalid result array dimensions: ~a" (array-dimensions page))
101
   (flet ((term-aspect-encoder (term-type term-literal term-language-tag term-datatype)
102
            (encode-turtle-term-aspects term-type term-literal term-language-tag term-datatype stream)))
103
     (declare (dynamic-extent #'term-aspect-encoder))
104
     (let ((term-deconstructor (repository-term-deconstructor *transaction*))
105
           (width (array-dimension page 1))
106
           (default-graph-term (when *nquads-default-graph-term* (iri-lexical-form *nquads-default-graph-term*))))
107
       (dotimes (page-index (array-dimension page 0))
108
         (when (>= index start)
109
           (when (and end (>= index end))
110
             (return))
111
           (loop for value-index from 0 below width
112
                 do (let ((term-id (aref page page-index value-index)))
113
                      ;; (print (list page-index value-index term-id))
114
                      (case term-id
115
                        (0
116
                         (if (= value-index 3)
117
                             (when default-graph-term
118
                               (format stream "<~a>" default-graph-term))
119
                             (ecase *ntriples-unbound-term-mode*
120
                               (spocq:unbound-variable
121
                                (format stream "<urn:dydra:unbound~@[:~a~]>" (nth value-index variables)))
122
                               (error
123
                                (error "invalid null ntriples/nquads term.")))))
124
                        ((-1 4294967295)
125
                         ;; suppress the term as the graph designator
126
                         (if (= value-index 3)
127
                             (when default-graph-term
128
                               (format stream "<~a>" default-graph-term))))
129
                        ((-2 4294967294)
130
                         (write-string "<urn:dydra:named>" stream))
131
                        (t
132
                         (funcall term-deconstructor #'term-aspect-encoder *transaction* term-id)))
133
                      (write-char #\space stream)))
134
           (write-char #\. stream)
135
           (nquads-eol stream))
136
         (incf index))))
137
   index)
138
 
139
 ;;;
140
 
141
 (defmethod send-response-message (operation (message t) (stream t) (content-type mime:text/plain))
142
   "Given a MESSAGE, and a STREAM with the text/plain CONTENT-TYPE, encode as ntriples"
143
   (when *encoding-trace-output*
144
     (setf stream (make-broadcast-stream *encoding-trace-output* stream)))
145
   (let ((*package* *spocq-reader-package*))
146
     (write-rdf-nquads message stream)))
147
 
148
 (defmethod send-response-message (operation (message t) (stream t) (content-type mime:application/n-triples))
149
   "Given a MESSAGE, and a STREAM with the application/n-triples CONTENT-TYPE, encode as ntriples"
150
   (when *encoding-trace-output*
151
     (setf stream (make-broadcast-stream *encoding-trace-output* stream)))
152
   (let ((*package* *spocq-reader-package*))
153
     (write-rdf-nquads message stream)))
154
 
155
 (defmethod send-response-message (operation (message t) (stream t) (content-type mime:application/n-quads))
156
   "Given a MESSAGE, and a STREAM with the application/n-quads CONTENT-TYPE, encode as nquads"
157
   (when *encoding-trace-output*
158
     (setf stream (make-broadcast-stream *encoding-trace-output* stream)))
159
   (let ((*package* *spocq-reader-package*))
160
     (write-rdf-nquads message stream)))
161
 
162
 #|
163
 (test-sparql "describe ?s where { ?s <http://example.org/identifier> 'c878cd60-0e0b-11e9-9fc2-010203040506'}"
164
   :repository-id "jhacker/test"
165
   :response-content-type mime:application/n-quads)
166
 |#