Coverage report: /development/source/library/org/datagraph/spocq-shard/src/algebra/operators/graph.lisp

KindCoveredAll%
expression98158 62.0
branch2240 55.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
 
3
 (in-package :org.datagraph.spocq.implementation)
4
 
5
 (:documentation "This file defines the for GRAPH operator interface for the 'org.datagraph.spocq'
6
  RDF engine."
7
 
8
  (copyright
9
   "Copyright 2010 [james anderson](mailto:james.anderson@setf.de) All Rights Reserved.")
10
 
11
  (long-description
12
   "The graph operator augments a constituent bgp with a term for the context/graph(s) against
13
  which to match the triple paterns. The interfac eoperaotr rewrites the graph form into an
14
  augmented bgp, by adding a graph form as one of the bgp's constituent terms, to be later used
15
  as an aspect of the bgp match/resolution. This simple rewriting defers the actual matching logic, as 
16
  that depends on several other elements of the query expression and of the query environment.
17
 
18
  - which (if any) graphs are specified by the request protocol or the dataset clause of the query
19
    itself. (see SQL4RDF, section [8.2](http://www.w3.org/TR/rdf-sparql-query/#specifyingDataset).)
20
  - which graphs are made available if no dataset is specified. these include
21
    - the repository's default "graph", (designated in lisp as t, in rdfcache as the value of
22
      rdfcache:*default-context-number*)
23
    - the repository's named graphs
24
  - the bindings matched elsewhere in the query for a variable in the graph clause.
25
  - the presence of a literal value as the graph designaor in the graph clause.
26
 
27
  The primitive triple match interface expresses both the pattern and the matches in terms of quads.
28
  hat is, each includes a graph/contxt term. Each of the situations affect the argument and/or result
29
  value for this term.
30
 
31
  - if a bgp is within a graph clause, and the graph term is variable
32
    - if named graphs are declared (via protocol or declared), then the match process iterates over
33
      those graphs and specifies each in turn as the context/graph argument to the query operator.
34
      if, in this case, the graph variable appears also elsewhere in the query, bgp ordering should
35
      prefer the graph clause over other bgp clauses and either the respective solutions will
36
      be unified or any propagation should be from the graph clause to the other clause(s).
37
    - if no named graph is declared, the graph argument is specified as wild and the results
38
      reflect matches among all named graphs in the repository. That domain does not include the
39
      default graph.
40
      If, in this case, the graph variable appears also elsewhere in the query, bgp ordering should
41
      prefer the other clause over the bgp clause and either the respective solutions will
42
      be unified or any propagation should be from the other clause(s) to the graph clause.
43
 
44
  - if a bgp is within a graph clause, and the graph term is a literal, then no iteration occurs.
45
    That literal value is supplied as the context/graph term to the query operator. There is no effect
46
    on bgp precedence.
47
 
48
  - if a bgp is autonomous, then the effective graph term still bound - implicitly, to the default graph(s).
49
    - if non-named graphs are declared (via protocol or declared), then the match process iterates over
50
      those graphs and specifies each in turn as the context/graph argument to the query operator.
51
    - if no non-named graph is declared, then the graph argument is bound to the repository's default
52
      graph. This is designated by the result of the rdfcache:*default-context-number*.
53
 
54
  See store/processing.lisp for the implementation."))
55
 
56
 (defparameter *graph-mode* ()
57
   "a list of graph processing options")
58
 
59
 (defmacro spocq.a:|graph| (name group-graph-pattern)
60
   "( ( (or anyURI variable) graphPattern ) solutionField )
61
 A GRAPH form modifies the application of a basic group graph pattern to either
62
 - constrain its extent to the specific graph named by the constant IRI, or
63
 - limit its domain to those named graphs enumerated in the dataset definition, or
64
 - permit it to range over all named graphs.
65
 In the latter two cases, the result solution field will include a binding for the respective graph
66
 in each solution.
67
 "
68
   (macroexpand-graph name group-graph-pattern))
69
 
70
 (defun macroexpand-graph (name group-graph-pattern)
71
   "Walk the constituent expression and add the graph to any immediately apparent bgp.
72
  Stop at any graph expression as that governs anything it its scope.
73
  Any select - thus a subselect may have a projection. In which case, if the graph is a variable which
74
  appears in the body but is not projected, then the body must be alpha-converted and the graph variable
75
  added to the projection."
76
 
77
   (if (and (find :implicit-federation *graph-mode*)
78
            (not (eq (federation-mode) '|urn:dydra|:|none|))
79
            (iri-p name)
80
            (zerop (repository-pattern-count *repository* nil nil nil name)))
81
     ;; for implicit graph federations, rewrite the graph form to a service form
82
     `(spocq.a:|service| ,name ,group-graph-pattern :silent t)
83
     ;; if either no federation at all, or limit to service forms
84
     (labels ((projected-variable-p (variable projection-specification)
85
                (loop for projection in projection-specification
86
                  when (typecase projection
87
                         (symbol (eq projection variable))
88
                         (cons (eq (first projection) variable)))
89
                  return t))
90
              (split-projection-specification (projection-specification)
91
                (values (loop while (keywordp (first projection-specification))
92
                          collect (pop projection-specification)
93
                          collect (pop projection-specification))
94
                        projection-specification))
95
              (merge-dimension (name projection-specification)
96
                 (loop for projection in projection-specification
97
                   when (and name (string< name (etypecase projection
98
                                                  (symbol projection)
99
                                                  (cons (first projection)))))
100
                   collect (shiftf name nil)
101
                   collect projection))
102
              (augment-bgps (expression)
103
                (cond ((bgp-form-p expression)
104
                       `(spocq.a:|bgp| (spocq.a:|graph| ,name)
105
                                       ,@(rest expression)))
106
                      ((graph-form-p expression)
107
                       ;; copy the tree to prevent further rewriting
108
                       (copy-list expression))
109
                      ((table-form-p expression)
110
                       `(spocq.a:|table| ,(when (variable-p name) (list name)) :graph ,name))
111
                      ((select-form-p expression)
112
                       (destructuring-bind (select field-expression projection-specification &rest args)
113
                                           expression
114
                         (declare (ignore select))
115
                         (multiple-value-bind (aggregation-clauses projection-specification)
116
                                              (split-projection-specification projection-specification)
117
                           (unless (consp projection-specification)
118
                             (setf projection-specification (expression-variables field-expression)))
119
                           ;; account for variations in whether
120
                           ;; - the graph name is projected
121
                           ;; - it is present in the field expression
122
                           ;; - it is added to some bgp in the field expression
123
                           (cond ((projected-variable-p name projection-specification)
124
                                  ;; iff the identical variable was projected, then the graph term shares scope with it
125
                                (setf field-expression (map-tree #'augment-bgps field-expression))
126
                                  (setf projection-specification (expression-variables field-expression))
127
                                  `(spocq.a:|select| ,field-expression ,projection-specification ,@args))
128
                                 ((variable-p name)
129
                                  ;; otherwise, alpha-convert to distinguish the graph variable from anything which
130
                                  ;; should not escape the select
131
                                  (setf field-expression (map-tree #'augment-bgps
132
                                                                   (sublis (list (cons name (cons-variable (string name))))
133
                                                                           field-expression)))
134
                                  ;; if the graph is visisble from some bgp, add it to the projection
135
                                  (when (member name (expression-variables field-expression))
136
                                    (setf projection-specification (merge-dimension name projection-specification)))
137
                                  `(spocq.a:|select| ,field-expression ,(append aggregation-clauses projection-specification) ,@args))
138
                               (t
139
                                ;; non-variables can augment a bgp, but cannot change the projection
140
                                `(spocq.a:|select| ,(map-tree #'augment-bgps field-expression)
141
                                                   ,(append aggregation-clauses projection-specification)
142
                                                   ,@args))))))
143
                      ((service-form-p expression)
144
                       ;; expand a base field, but otherwise just copy to prevent further rewriting
145
                        (destructuring-bind (op location group-graph-pattern &rest args) expression
146
                          (if (or (null args) (keywordp (first args)))
147
                              (copy-list expression)
148
                              (destructuring-bind (field &rest args) args
149
                                `(,op ,location ,group-graph-pattern ,(augment-bgps field) ,@args)))))
150
                      ((revision-form-p expression)
151
                       ;; propagate the graph in all cases
152
                       (destructuring-bind (op location group-graph-pattern &rest args) expression
153
                          (if (or (null args) (keywordp (first args)))
154
                              `(,op ,location ,(augment-bgps group-graph-pattern) ,@args)
155
                              (destructuring-bind (field &rest args) args
156
                                `(,op ,location ,group-graph-pattern ,(augment-bgps field) ,@args)))))
157
                      (t
158
                       expression))))
159
       (declare (dynamic-extent #'augment-bgps))
160
       (map-tree #'augment-bgps group-graph-pattern))))
161
 
162
 
163
 ;;; (spocq.a:|graph| ?::y (spocq.a:|bgp| (spocq.a:|triple| "aaa" ?::x (get-time))))
164
 ;;; (inspect (macroexpand '(spocq.a:|graph| ?::y (spocq.a:|bgp| (spocq.a:|triple| "aaa" ?::x (get-time))))))
165
 ;;; (spocq.a:|graph| "g" (spocq.a:|bgp| (spocq.a:|triple| "aaa" ?::x (get-time))))
166
 
167
 #|
168
 
169
 PREFIX foaf: <http://xmlns.com/foaf/0.1/>
170
 PREFIX data: <http://example.org/foaf/>
171
 
172
 SELECT ?nick
173
 FROM NAMED <http://example.org/foaf/aliceFoaf>
174
 FROM NAMED <http://example.org/foaf/bobFoaf>
175
 WHERE
176
   {
177
      GRAPH data:bobFoaf {
178
          ?x foaf:mbox <mailto:bob@work.example> .
179
          ?x foaf:nick ?nick 
180
          OPTIONAL { ?y foaf:nick ?nickY }}
181
   }
182
 |#