Coverage report: /development/source/library/org/datagraph/spocq-shard/src/core/encoding/sparql-query-graphviz.lisp
| Kind | Covered | All | % |
| expression | 0 | 1175 | 0.0 |
| branch | 0 | 10 | 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; -*-
2
;;; (load #p"patches/graph.lisp")
4
(in-package :org.datagraph.spocq.implementation)
6
;;; (load #p"LIBRARY:org;datagraph;spocq;src;core;encoding;graph.lisp")
8
(:documentation "generate a visual graph of a query"
9
"This is a simple recursive descent .dot generator based on the sse operators")
11
(defgeneric graph-query (query destination &rest options)
12
(:method ((query t) (destination pathname) &rest options)
13
(with-open-file (stream destination :direction :output :if-exists :supersede :if-does-not-exist :create)
14
(apply #'graph-query query stream options)))
15
(:method ((query t) (destination stream) &rest options)
16
(apply #'encode-graph query destination mime:text/VND.DYDRA.SPARQL-QUERY-ALGEBRA+GRAPHVIZ
18
(:method ((query string) (destination t) &rest options)
19
(apply #'graph-query (parse-sparql query) destination options)))
22
(defmethod context-encode-graph-as (context (task task) (as mime:graphviz))
23
(context-graph-sse context (task-sse-expression task)))
25
(defmethod context-encode-graph-as (context (query list) (as mime:graphviz))
26
(context-graph-sse context query))
28
(defmethod context-encode-graph-as (context (query null) (as mime:graphviz))
31
(defgeneric anonymize-graph-term (term)
32
(:method ((object spocq:iri))
33
(or (gethash object *graph-anonymous-map*)
34
(setf (gethash object *graph-anonymous-map*) (spocq:make-iri (string (gensym "iri-"))))))
35
(:method ((object string) )
36
(or (gethash object *graph-anonymous-map*)
37
(setf (gethash object *graph-anonymous-map*) (string (gensym "string-")))))
41
(defun cl-user::format-graph-term (stream term &optional colon at)
42
(declare (ignore colon at))
43
(encode-graph-term term stream))
45
(defgeneric encode-graph-term (term stream)
46
(:method ((term spocq:iri) stream)
47
(let ((q-name (iri-qname (puri:uri term)))
48
(namestring (iri-lexical-form term)))
50
(write-string q-name stream)
51
(format stream "<~/format-turtle-iri-namestring/>" namestring))))
52
(:method ((term symbol) stream)
54
(let ((q-name (iri-qname (puri:uri term)))
55
(namestring (symbol-uri-namestring term)))
57
(write-string q-name stream)
58
(format stream "<~/format-turtle-iri-namestring/>" namestring))))
60
(format stream "?~a" term))
62
(format stream "~a" term))))
63
(:method ((term t) (stream t))
64
(encode-turtle-object (if *graph-anonymous-map* (anonymize-graph-term term) term) stream))
65
(:method ((term property-path) (stream t))
66
(print-object term stream)))
69
(defgeneric context-graph-sse-op (context operator arguments)
70
(:documentation "Graph the expression operator given its arguments.")
71
(:method ((context t) (operator (eql 'let)) parameters)
72
(context-graph-sse context (third parameters)))
73
(:method ((context t) (operator null) parameters)
76
(defgeneric context-graph-sse (context query)
77
(:method ((context t) (sse list))
78
(context-graph-sse-op context (first sse) (rest sse))))
81
(defun graph-term-string (term)
82
(let ((*encode-turtle-object-as-variable-p* t))
83
(with-output-to-string (stream)
84
(encode-graph-term term stream))))
86
(defun graph-term-string (term)
87
(graph-expression-string term))
89
(defun graph-expression-string (expression)
90
(let ((*encode-turtle-object-as-variable-p* t))
92
(with-output-to-string (stream)
93
(labels ((encode-expression (expression)
95
(cons (case (first expression)
96
(spocq.a:|exprlist| (format-sparql-sse-expression stream expression))
98
(encode-expression (third expression)))
100
(write-string "(" stream)
101
(loop for term in expression
102
do (progn (write-char #\space stream)
103
(encode-expression term)))
104
(write-string " )" stream))))
105
((satisfies variable-p) (format stream "?~a" expression))
106
(symbol (format stream "~a" expression))
107
(t (encode-graph-term expression stream)))))
108
(encode-expression expression))))))
110
(defun test-expression-string (test-expression)
111
(with-output-to-string (stream)
112
(loop for char across (with-output-to-string (stream)
113
(case (first test-expression)
115
(format stream "~{~/format-sparql-expression/~^ &&~}" (rest test-expression)))
116
(t (format stream "~/format-sparql-expression/" test-expression))))
118
do (write-char char stream)
121
(when (= (incf count) 2)
123
(write-string "\\n" stream)))))))
126
(defun graph-triple-string (s p o &rest properties)
127
(declare (ignore properties))
128
(let ((*encode-turtle-object-as-variable-p* t))
129
(with-output-to-string (stream)
130
(encode-graph-term s stream)
131
(write-char #\space stream)
132
(encode-graph-term p stream)
133
(write-char #\space stream)
134
(encode-graph-term o stream))))
136
(defun graph-quad-string (s p o c &rest properties)
137
(declare (ignore properties))
138
(let ((*encode-turtle-object-as-variable-p* t))
139
(with-output-to-string (stream)
140
(encode-graph-term s stream)
141
(write-char #\space stream)
142
(encode-graph-term p stream)
143
(write-char #\space stream)
144
(encode-graph-term o stream)
145
(write-char #\space stream)
146
(encode-graph-term c stream))))
149
(macrolet ((def-graph-method (operator lambda-list &body body)
150
(let* ((body-non-decl (member 'declare body :test-not #'eq :key #'first))
151
(decls (ldiff body body-non-decl)))
152
(declare (ignore decls))
153
`(defmethod context-graph-sse-op ((context t) (operator (eql ',operator)) parameters)
154
(destructuring-bind ,lambda-list parameters
158
(def-graph-method spocq.a:|agp| (&rest triples)
159
(let ((id (gensym "agp")))
160
(encode-sparql-graph-node (id "agp")
161
(ecase *graph-bgp-mode*
163
(dot:context-put-node context id :label (format nil "agp~@[ @ ~/format-graph-term/~]~{\\n~a~}"
164
(second (assoc 'spocq.a:|graph| triples))
165
(mapcar #'(lambda (triple)
167
((spocq.a:|triple| spocq.a:|quad|)
168
(apply #'graph-triple-string (rest triple)))))
172
(dot:context-put-node context id :label (format nil "agp~@[ @ ~/format-graph-term/~]"
173
(second (assoc 'spocq.a:|graph| triples))))
174
(dolist (triple triples)
179
((spocq.a:|triple| spocq.a:|quad|)
180
(dot:context-put-edge context id (context-graph-sse context triple)
184
(def-graph-method spocq.a:|ask| (expression)
185
(let ((id (gensym "ask")))
186
(dot:context-put-node context id :label "ask")
187
(dot:context-put-edge context id (context-graph-sse context expression))
190
(def-graph-method spocq.e:ask (expression)
191
(let ((id (gensym "ask")))
192
(dot:context-put-node context id :label "ASK")
193
(dot:context-put-edge context id (context-graph-sse context expression))
197
(def-graph-method spocq.a:|bgp| (&rest triples)
198
(let ((id (gensym "bgp")))
199
(encode-sparql-graph-node (id "bgp")
200
(ecase *graph-bgp-mode*
202
(dot:context-put-node context id :label (format nil "bgp~{\\n~a~}"
203
(remove-if #'undistinguished-variable-p (expression-variables triples)))))
205
(dot:context-put-node context id :label (format nil "bgp~{\\n~a~}"
206
(mapcar #'(lambda (triple) (apply #'graph-triple-string (rest triple)))
210
(dot:context-put-node context id :label "bgp")
211
(dolist (triple triples)
213
((spocq.a:|triple| spocq.a:|quad|)
214
(dot:context-put-edge context id (context-graph-sse context triple)
218
(def-graph-method spocq.a:|bindings| (expressions variables)
219
(let ((id (gensym "bindings")))
220
(encode-sparql-graph-node (id "values")
221
(dot:context-put-node context id :label (format nil "bind (~{?~a~^ ~}) :~:[ ()~;~:*\\n(~{(~{~/format-graph-term/~^ ~})~^\\n ~})~]"
223
(typecase expressions
225
(array (loop for i from 0 below (array-dimension expressions 0)
226
collect (loop for j from 0 below (array-dimension expressions 1))))))))
228
(def-graph-method spocq.e:bindings (expressions variables)
229
(context-graph-sse context `(spocq.a:|bindings| ,(second expressions) ,(second variables))))
233
(def-graph-method spocq.a:|construct| (solution-field triples &optional continuation)
234
(declare (ignore continuation))
235
(let ((id (gensym "construct"))
236
(*print-pretty* nil))
237
(encode-sparql-graph-node (id "construct")
238
(dot:context-put-node context id :label (format nil "construct~{\\n~a~}"
239
(mapcar #'(lambda (stmt)
241
(spocq.a:|triple| (apply #'graph-triple-string (rest stmt)))
242
(spocq.a:|quad| (apply #'graph-quad-string (rest stmt)))))
246
(if (> (length triples) 1)
247
(dot:context-put-node context id :label (format nil "construct (~{~% ~a~})" triples))
248
(dot:context-put-node context id :label (format nil "construct (~{\\n ~a~})" triples)))
249
(dot:context-put-edge context id (context-graph-sse context solution-field)
253
(def-graph-method spocq.e:construct (solution-field triples)
254
(let ((id (gensym "CONSTRUCT"))
255
(*print-pretty* nil))
256
(when (eq (first triples) 'quote)
257
(setf triples (second triples)))
258
(encode-sparql-graph-node (id "CONSTRUCT")
259
(dot:context-put-node context id :label (format nil "CONSTRUCT~{\\n~a~}"
260
(mapcar #'(lambda (stmt)
262
(spocq.a:|triple| (apply #'graph-triple-string (rest stmt)))
263
(spocq.a:|quad| (apply #'graph-quad-string (rest stmt)))))
267
(if (> (length triples) 1)
268
(dot:context-put-node context id :label (format nil "construct (~{~% ~a~})" triples))
269
(dot:context-put-node context id :label (format nil "construct (~{\\n ~a~})" triples)))
270
(dot:context-put-edge context id (context-graph-sse context solution-field)
277
(def-graph-method spocq.a:|describe| (solution-field subjects &optional continuation)
278
(declare (ignore continuation))
279
(let ((id (gensym "describe")))
280
(encode-sparql-graph-node (id "describe")
281
(dot:context-put-node context id :label (format nil "describe ~a" subjects)))
282
(dot:context-put-edge context id (context-graph-sse context solution-field)
286
(def-graph-method spocq.a:|diff| (solution-field1 solution-field2 test-expression)
287
(let ((id (gensym "diff")))
288
(encode-sparql-graph-node (id "diff")
289
(dot:context-put-node context id :label (format nil "diff ~a" (graph-expression-string test-expression))))
290
(dot:context-put-edge context id (context-graph-sse context solution-field1)
292
(dot:context-put-edge context id (context-graph-sse context solution-field2)
296
(def-graph-method spocq.a:|distinct| (solution-field &key count end offset start)
297
(declare (ignore count end offset count start))
298
(let ((id (gensym "distinct")))
299
(encode-sparql-graph-node (id "distinct")
300
(dot:context-put-node context id :label "distinct"))
301
(dot:context-put-edge context id (context-graph-sse context solution-field)
305
(def-graph-method spocq.e:distinct (solution-field &rest args)
306
(context-graph-sse context `(spocq.a:|distinct| ,solution-field ,@args)))
309
(def-graph-method spocq.a:|extend| (solution-field variable expression)
310
(let ((id (gensym "extend")))
311
(encode-sparql-graph-node (id "extend")
312
(dot:context-put-node context id :label (format nil "extend ?~a :\\n ~a"
314
(graph-expression-string expression))))
315
(dot:context-put-edge context id (context-graph-sse context solution-field)
319
(def-graph-method spocq.e:extend (solution-field bindings)
320
(let ((id (gensym "extend")))
321
(encode-sparql-graph-node (id "extend")
322
(dot:context-put-node context id :label (format nil "extend (~{(~{?~a ~a~})~^\\n ~})"
323
(loop for (variable expression) in (second bindings)
324
collect (list variable (graph-expression-string expression))))))
325
(dot:context-put-edge context id (context-graph-sse context solution-field)
329
(def-graph-method spocq.a:|filter| (solution-field test-expression &key offset count)
330
(declare (ignore offset count))
331
(let ((id (gensym "filter")))
332
(encode-sparql-graph-node (id "filter")
333
(let ((constraint (test-expression-string test-expression)))
334
(dot:context-put-node context id :label (format nil "filter (~a)" constraint))))
335
(dot:context-put-edge context id (context-graph-sse context solution-field)
338
(def-graph-method spocq.e:filter (solution-field test-expression &rest args)
339
(context-graph-sse context `(spocq.a:|filter| ,solution-field ,(second test-expression) ,@args)))
341
(def-graph-method spocq.a:|graph| (name group-graph-pattern)
342
(let ((id (gensym "graph")))
343
(encode-sparql-graph-node (id "graph")
344
(dot:context-put-node context id :label (format nil "graph ~a" (graph-term-string name))))
345
(dot:context-put-edge context id (context-graph-sse context group-graph-pattern)
351
(def-graph-method spocq.a:|join| (solution-field1 solution-field2 &key offset count)
352
(declare (ignore offset count))
353
(let ((id (gensym "join")))
354
(encode-sparql-graph-node (id "join")
355
(dot:context-put-node context id :label "join"))
356
(dot:context-put-edge context id (context-graph-sse context solution-field1)
358
(dot:context-put-edge context id (context-graph-sse context solution-field2)
362
(def-graph-method spocq.e:join (solution-field1 solution-field2 &key test offset count)
363
(declare (ignore offset count))
364
(let ((id (gensym "join"))
365
(constraint (when test (test-expression-string test))))
366
(encode-sparql-graph-node (id "join")
367
(dot:context-put-node context id :label (if constraint (format nil "join (~a)" constraint) "join")))
368
(dot:context-put-edge context id (context-graph-sse context solution-field1)
370
(dot:context-put-edge context id (context-graph-sse context solution-field2)
374
(def-graph-method spocq.a:|leftjoin| (solution-field1 solution-field2 &key test offset count)
375
(declare (ignore offset count))
376
(let ((id (gensym "leftjoin")))
377
(encode-sparql-graph-node (id "leftjoin")
378
(dot:context-put-node context id :label (format nil "leftjoin~@[ ~a~]" (graph-expression-string test))))
379
(dot:context-put-edge context id (context-graph-sse context solution-field1)
381
(dot:context-put-edge context id (context-graph-sse context solution-field2)
384
(def-graph-method spocq.e:leftjoin (solution-field1 solution-field2 &rest args)
385
(context-graph-sse context `(spocq.a:|leftjoin| ,solution-field1 ,solution-field2 ,@args)))
388
(def-graph-method spocq.a:|minus| (solution-field1 solution-field2 &key offset count)
389
(declare (ignore offset count))
390
(let ((id (gensym "minus")))
391
(encode-sparql-graph-node (id "minus")
392
(dot:context-put-node context id :label "minus"))
393
(dot:context-put-edge context id (context-graph-sse context solution-field1)
395
(dot:context-put-edge context id (context-graph-sse context solution-field2)
401
(def-graph-method spocq.a:|null| (dimensions)
402
(let ((id (gensym "null")))
403
(encode-sparql-graph-node (id "null")
404
(dot:context-put-node context id :label (format nil "null ~a" dimensions)))
407
(def-graph-method spocq.a:|order| (solution-field order-expression-list)
408
(let ((id (gensym "order")))
409
(encode-sparql-graph-node (id "order")
410
(dot:context-put-node context id :label (format nil "order ~a" order-expression-list)))
411
(dot:context-put-edge context id (context-graph-sse context solution-field)
415
(def-graph-method spocq.a:|project| (solution-field variables &key offset count)
416
(declare (ignore offset count))
417
(let ((id (gensym "project")))
418
(dot:context-put-node context id :label (format nil "project ~a" variables))
419
(dot:context-put-edge context id (context-graph-sse context solution-field)
423
(def-graph-method spocq.e:project (solution-field variables &rest args)
424
(context-graph-sse context `(spocq.a:|project| ,solution-field ,(second variables) ,@args)))
426
(def-graph-method spocq.a:|quad| (s p o c &rest properties)
427
(declare (ignore properties))
428
(let ((id (gensym "triple")))
429
(dot:context-put-node context id :label (format nil "(~a)" (graph-quad-string s p o c)))
432
(def-graph-method spocq.a:|reduced| (solution-field &key offset count)
433
(declare (ignore offset count))
434
(let ((id (gensym "reduced")))
435
(encode-sparql-graph-node (id "reduced")
436
(dot:context-put-node context id :label "reduced"))
437
(dot:context-put-edge context id (context-graph-sse context solution-field)
442
(def-graph-method spocq.a:|select| (solution-field variables &optional continuation)
443
(declare (ignore continuation))
444
(let ((id (gensym "select")))
445
(encode-sparql-graph-node (id "select")
446
(dot:context-put-node context id :label (format nil "select ~a" (mapcar #'graph-term-string variables)) :shape "box"))
447
(dot:context-put-edge context id (context-graph-sse context solution-field)
451
(def-graph-method spocq.a:|service| (name group-graph-pattern &rest args)
452
(if (symbolp (first args)) ;; ignore text
453
(let ((id (gensym "service"))
454
(endpoint-id (gensym "endpoint")))
455
(encode-sparql-graph-node (id "service")
456
(dot:context-put-node context id :label (format nil "service ~a" (graph-term-string name))))
457
(dot:context-put-node context endpoint-id :label (graph-term-string name) :color "red")
458
(dot:context-put-edge context id (context-graph-sse context group-graph-pattern)
460
(dot:context-put-edge context id endpoint-id :style "dashed" :dir "both")
462
;; allow both as service form
463
(context-graph-sse context
464
`(spocq.a:|servicejoin| ,name ,group-graph-pattern ,@args))))
465
(def-graph-method spocq.e:service (name group-graph-pattern &rest args)
466
(context-graph-sse context `(spocq.a:|service| ,(second name) ,(second group-graph-pattern) ,@args)))
468
(def-graph-method spocq.a:|servicejoin| (name group-graph-pattern source-graph-pattern &rest args)
469
(declare (ignore args))
470
(print (list name group-graph-pattern source-graph-pattern))
471
(let ((id (gensym "service"))
472
(endpoint-id (gensym "endpoint")))
473
(encode-sparql-graph-node (id "service")
474
(dot:context-put-node context id :label (format nil "servicejoin ~a" (graph-term-string name))))
475
(dot:context-put-node context endpoint-id :label (graph-term-string name) :color "red")
476
(dot:context-put-edge context id (context-graph-sse context group-graph-pattern)
478
(dot:context-put-edge context id (context-graph-sse context source-graph-pattern)
480
(dot:context-put-edge context id endpoint-id :style "dashed" :dir "both")
482
(def-graph-method spocq.e:service-join (name group-graph-pattern source-graph-pattern &rest args)
483
(context-graph-sse context `(spocq.a:|servicejoin| ,(second name) ,(second group-graph-pattern) ,source-graph-pattern ,@args)))
485
(def-graph-method spocq.a::|serviceleftjoin| (name group-graph-pattern source-graph-pattern &rest args)
486
(declare (ignore args))
487
(print (list name group-graph-pattern source-graph-pattern))
488
(let ((id (gensym "service"))
489
(endpoint-id (gensym "endpoint")))
490
(encode-sparql-graph-node (id "service")
491
(dot:context-put-node context id :label (format nil "serviceleftjoin ~a" (graph-term-string name))))
492
(dot:context-put-node context endpoint-id :label (graph-term-string name) :color "red")
493
(dot:context-put-edge context id (context-graph-sse context group-graph-pattern)
495
(dot:context-put-edge context id (context-graph-sse context source-graph-pattern)
497
(dot:context-put-edge context id endpoint-id :style "dashed" :dir "both")
500
(def-graph-method spocq.e::service-leftjoin (name group-graph-pattern source-graph-pattern &rest args)
501
(context-graph-sse context `(spocq.a::|serviceleftjoin| ,(second name) ,(second group-graph-pattern) ,source-graph-pattern ,@args)))
503
(def-graph-method spocq.a:|slice| (expression &key offset count)
504
(let ((id (gensym "select")))
505
(encode-sparql-graph-node (id "select")
506
(dot:context-put-node context id :label (format nil "slice (~a x ~a)" offset count)))
507
(dot:context-put-edge context id (context-graph-sse context expression)
511
(def-graph-method spocq.a:|table| (&optional dimensions)
512
(let ((id (gensym "table")))
513
(encode-sparql-graph-node (id "table")
514
(dot:context-put-node context id :label (format nil "table~@[ ~a~]" dimensions)))
517
(def-graph-method spocq.a:|to-list| (solution-field)
518
(let ((id (gensym "to-list")))
519
(encode-sparql-graph-node (id "to-list")
520
(dot:context-put-node context id :label "to-list"))
521
(dot:context-put-edge context id (context-graph-sse context solution-field))
524
(def-graph-method spocq.a:|triple| (s p o &rest properties)
525
(declare (ignore properties))
526
(let ((id (gensym "triple")))
527
(encode-sparql-graph-node (id "triple")
528
(dot:context-put-node context id :label (format nil "(~a)" (graph-triple-string s p o))))
531
(def-graph-method spocq.a:|union| (solution-field1 solution-field2)
532
(let ((id (gensym "union")))
533
(encode-sparql-graph-node (id "union")
534
(dot:context-put-node context id :label "union"))
535
(dot:context-put-edge context id (context-graph-sse context solution-field1)
537
(dot:context-put-edge context id (context-graph-sse context solution-field2)
541
(def-graph-method spocq.e:union (solution-field1 solution-field2)
542
(let ((id (gensym "union")))
543
(encode-sparql-graph-node (id "UNION")
544
(dot:context-put-node context id :label "UNION"))
545
(dot:context-put-edge context id (context-graph-sse context solution-field1)
547
(dot:context-put-edge context id (context-graph-sse context solution-field2)
551
(def-graph-method spocq.e::with-join-scope (scope expression)
552
(declare (ignore scope))
553
(context-graph-sse context expression))