Coverage report: /development/source/library/org/datagraph/spocq-shard/src/core/encoding/application-ndjson.lisp
| Kind | Covered | All | % |
| expression | 0 | 233 | 0.0 |
| branch | 0 | 24 | 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)
5
(:documentation "application/x-ndjson serializer"
6
"see https://github.com/ndjson/ndjson-spec
10
;;; writing - either boolean or bindings
12
(defgeneric write-sparql-results-application+x-ndjson (results stream)
13
(:documentation "Encode the result field to the stream as primitive json objects w/o any correlation,
14
but without json array syntay-")
16
(:method ((result symbol) (stream t))
17
(format stream "{\"boolean\": ~a}"
18
(spocq.e:boolean result))
19
(incf-stat *statements-returned*))
21
(:method ((results list-solution-field) (stream t))
22
(write-sparql-results-application+json (cons (list-solution-field-dimensions results)
23
(list-solution-field-solutions results))
26
(:method ((results cons) (stream t))
27
(let* ((variables (first results))
28
(solutions (rest results))
30
(start (or (response-offset) 0))
32
(dolist (result solutions)
33
(when (>= index start)
34
(when (and end (>= index end))
36
(format stream "~:[~;,~% ~] { " (> index start))
37
(loop for name in variables for value in result
40
;; emit non-null values and enable commas
41
((or null spocq:unbound-variable (member etf:nil)))
42
(t (format stream "~:[, ~;~]\"~a\": " first name)
44
(encode-json-term-compact value stream))))
48
(incf-stat *statements-returned* index)
51
(:method ((results boolean-generator) (stream t))
52
(let* ((channel (boolean-generator-channel results)))
53
(format stream "{\"boolean\": ~a}"
54
(spocq:literal-lexical-form (if (get-field-page channel) spocq.a:|true| spocq.a:|false|)))
55
(incf-stat *statements-returned*)))
57
(:method ((results solution-generator) (stream t))
58
(let* ((dimensions (solution-generator-dimensions results))
59
(channel (solution-generator-channel results))
60
(base-width (length dimensions))
62
(start (or (response-offset) 0))
64
(rlmdb::with-string-database (sdb)
65
(do-pages (page channel)
66
(if (and end (>= index end))
68
(if (>= (+ index (array-dimension page 0)) start)
69
(cond ((= base-width (array-dimension page 1))
70
(trace-data write-sparql-results+json dimensions (term-value-field page))
71
(setf index (write-sparql-results-field+ndjson page dimensions stream index start end)))
73
(log-warn "field width mismatch: ~s : ~s."
74
dimensions (array-dimension page 1))
75
(incf index (array-dimension page 0))))
76
; otherwise skip the entire page
77
(incf index (array-dimension page 0))))))
78
(incf-stat *statements-returned* index)
82
(:method ((result-field true-matrix-field) (stream t))
83
(format stream "{\"boolean\": ~a}" (spocq:literal-lexical-form spocq.a:|true|))
84
(incf-stat *statements-returned*))
86
(:method ((result-field false-matrix-field) (stream t))
87
(format stream "{\"boolean\": ~a}" (spocq:literal-lexical-form spocq.a:|false|))
88
(incf-stat *statements-returned*))
90
(:method ((result-field matrix-field) (stream t))
91
(flet ((term-aspect-encoder (term-type term-literal term-language-tag term-datatype)
92
(encode-json-term-aspects term-type term-literal term-language-tag term-datatype stream)))
93
(declare (dynamic-extent #'term-aspect-encoder))
94
(let ((term-deconstructor (repository-term-deconstructor *transaction*)))
95
(let* ((dimensions (solution-field-dimensions result-field))
96
(base-width (length dimensions))
97
(start (or (response-offset) 0))
101
(rlmdb::with-string-database (sdb)
102
(with-input-fields (result-field)
103
(let ((%source-data (cffi::null-pointer))
105
(setf (values %source-data source-row) (first-field-row result-field))
106
(loop until (and end (>= result-count (the fixnum end)))
107
until (cffi:null-pointer-p %source-data)
109
(trace-matrix "~& write-sparql-results+json.next ~@{~a ~}" :source-row source-row)
110
(when (> (incf result-count) start)
111
(format stream "~:[,~;~]~:[~;~%~] " (shiftf first nil) *print-pretty*)
112
(write-string " {" stream)
114
for term-offset from (* base-width source-row)
115
for name in dimensions
116
when (distinguished-variable-p name)
117
do (let ((term-id (#.+matrix-accessor+ (the sb-sys:system-area-pointer %source-data)
118
(the fixnum (* #.(cffi:foreign-type-size +matrix-element-type+) term-offset)))))
119
(unless (= term-id +null-term-id+)
120
(if (shiftf first nil) (write-char #\space stream) (format stream ", "))
121
(format stream "\"~a\": " name)
122
(funcall term-deconstructor #'term-aspect-encoder *transaction* term-id))))
123
(write-string " }" stream))
124
(setf (values %source-data source-row) (next-field-row result-field)))))))
125
(incf-stat *statements-returned* (- result-count start))
132
(defmethod send-response-message ((operation t) (message t) (stream t) (content-type mime:application/x-ndjson))
133
"Given a MESSAGE, and a STREAM with the application/x-ndjson CONTENT-TYPE, encode as json.
134
This is intended to subsume application/rdf+json as well."
135
(when *encoding-trace-output*
136
(setf stream (make-broadcast-stream *encoding-trace-output* stream)))
137
(let ((*package* *spocq-reader-package*))
138
(write-sparql-results-application+x-ndjson message stream)))
141
(write-sparql-results+x-ndjson '((?::a ?::s ?::z) (1 2 3) (<http://example/1> <http://example/2> <http://example/3>))