Coverage report: /development/source/library/org/datagraph/spocq-shard/src/core/encoding/sparql-results-tsv.lisp
| Kind | Covered | All | % |
| expression | 27 | 217 | 12.4 |
| branch | 0 | 20 | 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
;;; tsv serializer as streamed columns.
6
;;; each solution is (at least) one line, with the first containing the dimensions
7
;;; see http://www.w3.org/TR/sparql11-results-csv-tsv/
12
;;; writing - either boolean or bindings
14
(defun tsv-eol (stream)
15
(write-char #\newline stream))
17
(defun write-tsv-dimensions (dimensions stream)
19
(let ((dimension (pop dimensions)))
21
(format stream "?~a~c" dimension #\tab)
22
(format stream "?~a" dimension))
23
(write-tsv-dimensions dimensions stream))))
26
(defgeneric write-sparql-results+tsv (results stream)
27
(:documentation "Encode the result field to the stream as text/tsv.
28
The results are one solutions per line with commas between each term.
29
The first element is a header, which specifies the variable names.
30
The remaining entries are solutions sets. if a variable is unbound, there is no output.
31
If a string is blank, a pair of double quotes appears.")
33
(:method ((result symbol) (stream t))
34
(format stream "result~%")
35
(encode-turtle-object result stream)
37
(incf-stat *statements-returned*))
39
(:method ((results cons) (stream t))
40
(let* ((dimensions (first results))
41
(solutions (rest results))
43
(start (or (response-offset) 0))
45
(write-tsv-dimensions dimensions stream)
47
(dolist (result solutions)
48
(when (>= index start)
49
(when (and end (>= index end))
51
(loop for value in result
52
for first = t then nil
53
do (progn (unless first (write-char #\tab stream))
54
(unless (spocq:unbound-variable-p value)
55
(encode-turtle-object value stream)))))
58
(incf-stat *statements-returned* index)))
60
(:method ((results boolean-generator) (stream t))
61
(let* ((channel (boolean-generator-channel results)))
62
(format stream "?result")
64
(write-string (spocq:literal-lexical-form (if (get-field-page channel) spocq.a:|true| spocq.a:|false|)) stream)
66
(incf-stat *statements-returned*)))
68
(:method ((results solution-generator) (stream t))
69
(let* ((dimensions (solution-generator-dimensions results))
70
(channel (solution-generator-channel results))
71
(variable-count (length dimensions))
73
(start (or (response-offset) 0))
75
(flet ((term-aspect-encoder (term-type term-literal term-language-tag term-datatype)
76
(encode-turtle-term-aspects term-type term-literal term-language-tag term-datatype stream)))
77
(declare (dynamic-extent #'term-aspect-encoder))
78
(let ((term-deconstructor (repository-term-deconstructor *transaction*)))
79
(write-tsv-dimensions dimensions stream)
81
(do-pages (page channel)
82
(if (and end (>= index end))
84
(if (>= (+ index (array-dimension page 0)) start)
85
(cond ((= variable-count (array-dimension page 1))
86
(dotimes (page-index (array-dimension page 0))
87
(when (>= index start)
88
(when (and end (>= index end))
90
(loop for value-index from 0 below variable-count
91
do (progn (unless (zerop value-index) (write-char #\tab stream))
92
(let ((term-id (aref page page-index value-index)))
93
(cond ((= term-id +null-term-id+))
95
(funcall term-deconstructor #'term-aspect-encoder *transaction* term-id))))))
99
(log-warn "field width mismatch: ~s : ~s."
100
dimensions (array-dimension page 1))
101
(incf index (array-dimension page 0))))
102
; otherwise skip the entire page
103
(incf index (array-dimension page 0)))))))
104
(incf-stat *statements-returned* index))))
109
(defmethod send-error-message ((body t) (stream t) (content-type mime:text/tab-separated-values))
110
"Send an error response encoded as sse"
111
(send-error-message body stream mime:application/sparql-query+sse))
113
(defmethod send-response-message (operation (message-body t) (stream t)
114
(content-type mime:text/tab-separated-values))
115
"Given a MESSAGE, and a STREAM with the text/csv CONTENT-TYPE, encode as tsv, streamed"
116
(when *encoding-trace-output*
117
(setf stream (make-broadcast-stream *encoding-trace-output* stream)))
118
(let ((*package* *spocq-reader-package*)
119
(*expand-literal-values* nil))
120
(write-sparql-results+tsv message-body stream)))
122
(defgeneric tsv-sparql (query pathname &rest args)
123
(:method ((query t) (destination pathname) &rest args)
124
(with-open-file (output-stream destination :direction :output
125
:element-type 'character
126
:if-does-not-exist :create :if-exists :supersede)
127
(apply #'tsv-sparql query output-stream args)))
128
(:method ((query t) (destination stream) &rest args)
129
(multiple-value-bind (results dimensions *task*)
130
(apply #'run-sparql query args)
131
(let ((*expand-literal-values* nil))
133
(write-sparql-results+tsv (cons dimensions results)
137
(write-sparql-results+tsv '((?::a ?::s ?::z) (1 2 3) (<http://example/1> <http://example/2> <http://example/3>))
140
(write-sparql-results+tsv 'spocq.a:|true| *trace-output*)
142
(send-response-message :test
143
'((?::a ?::s ?::z) (1 2 3) (<http://example/1> <http://example/2> <http://example/3>))
145
mime:text/tab-separated-values)