sparql 3.2.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/VERSION +1 -1
- data/lib/sparql/algebra/expression.rb +28 -3
- data/lib/sparql/algebra/extensions.rb +36 -32
- data/lib/sparql/algebra/operator/abs.rb +1 -1
- data/lib/sparql/algebra/operator/alt.rb +1 -1
- data/lib/sparql/algebra/operator/avg.rb +3 -1
- data/lib/sparql/algebra/operator/bgp.rb +9 -1
- data/lib/sparql/algebra/operator/clear.rb +13 -3
- data/lib/sparql/algebra/operator/construct.rb +1 -1
- data/lib/sparql/algebra/operator/count.rb +36 -6
- data/lib/sparql/algebra/operator/create.rb +5 -4
- data/lib/sparql/algebra/operator/dataset.rb +19 -11
- data/lib/sparql/algebra/operator/delete.rb +3 -1
- data/lib/sparql/algebra/operator/delete_data.rb +1 -1
- data/lib/sparql/algebra/operator/delete_where.rb +1 -1
- data/lib/sparql/algebra/operator/distinct.rb +2 -2
- data/lib/sparql/algebra/operator/divide.rb +1 -1
- data/lib/sparql/algebra/operator/drop.rb +15 -6
- data/lib/sparql/algebra/operator/encode_for_uri.rb +2 -4
- data/lib/sparql/algebra/operator/exprlist.rb +3 -1
- data/lib/sparql/algebra/operator/extend.rb +36 -3
- data/lib/sparql/algebra/operator/filter.rb +1 -1
- data/lib/sparql/algebra/operator/function_call.rb +64 -0
- data/lib/sparql/algebra/operator/graph.rb +57 -7
- data/lib/sparql/algebra/operator/group.rb +76 -5
- data/lib/sparql/algebra/operator/group_concat.rb +25 -1
- data/lib/sparql/algebra/operator/if.rb +10 -10
- data/lib/sparql/algebra/operator/insert.rb +3 -1
- data/lib/sparql/algebra/operator/insert_data.rb +1 -1
- data/lib/sparql/algebra/operator/is_blank.rb +1 -2
- data/lib/sparql/algebra/operator/is_iri.rb +1 -2
- data/lib/sparql/algebra/operator/is_literal.rb +1 -2
- data/lib/sparql/algebra/operator/is_numeric.rb +1 -2
- data/lib/sparql/algebra/operator/join.rb +37 -3
- data/lib/sparql/algebra/operator/lcase.rb +2 -3
- data/lib/sparql/algebra/operator/left_join.rb +20 -7
- data/lib/sparql/algebra/operator/max.rb +3 -1
- data/lib/sparql/algebra/operator/min.rb +4 -2
- data/lib/sparql/algebra/operator/minus.rb +46 -6
- data/lib/sparql/algebra/operator/multiply.rb +1 -1
- data/lib/sparql/algebra/operator/notoneof.rb +12 -3
- data/lib/sparql/algebra/operator/order.rb +44 -0
- data/lib/sparql/algebra/operator/plus.rb +1 -1
- data/lib/sparql/algebra/operator/project.rb +22 -4
- data/lib/sparql/algebra/operator/reduced.rb +3 -3
- data/lib/sparql/algebra/operator/regex.rb +1 -1
- data/lib/sparql/algebra/operator/reverse.rb +12 -1
- data/lib/sparql/algebra/operator/sample.rb +3 -1
- data/lib/sparql/algebra/operator/seq.rb +1 -1
- data/lib/sparql/algebra/operator/sequence.rb +4 -1
- data/lib/sparql/algebra/operator/strlang.rb +1 -2
- data/lib/sparql/algebra/operator/subtract.rb +1 -1
- data/lib/sparql/algebra/operator/sum.rb +9 -7
- data/lib/sparql/algebra/operator/table.rb +41 -7
- data/lib/sparql/algebra/operator/ucase.rb +1 -1
- data/lib/sparql/algebra/operator/update.rb +22 -1
- data/lib/sparql/algebra/operator/using.rb +18 -1
- data/lib/sparql/algebra/operator/with.rb +1 -1
- data/lib/sparql/algebra/operator.rb +46 -18
- data/lib/sparql/algebra.rb +20 -3
- data/lib/sparql/grammar/parser11.rb +3 -3
- metadata +15 -2
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
module SPARQL; module Algebra
|
3
|
+
class Operator
|
4
|
+
##
|
5
|
+
# The SPARQL `function_call` operator.
|
6
|
+
#
|
7
|
+
# [70] FunctionCall ::= iri ArgList
|
8
|
+
#
|
9
|
+
# @example SPARQL Grammar
|
10
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
11
|
+
# SELECT *
|
12
|
+
# WHERE { ?s ?p ?o . FILTER xsd:integer(?o) }
|
13
|
+
#
|
14
|
+
# @example SSE
|
15
|
+
# (prefix
|
16
|
+
# ((xsd: <http://www.w3.org/2001/XMLSchema#>))
|
17
|
+
# (filter (xsd:integer ?o)
|
18
|
+
# (bgp (triple ?s ?p ?o))))
|
19
|
+
#
|
20
|
+
# @see https://www.w3.org/TR/sparql11-query/#funcex-regex
|
21
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-matches
|
22
|
+
class FunctionCall < Operator
|
23
|
+
include Evaluatable
|
24
|
+
|
25
|
+
NAME = :function_call
|
26
|
+
|
27
|
+
##
|
28
|
+
# Invokes the function with the passed arguments.
|
29
|
+
#
|
30
|
+
# @param [RDF::IRI] iri
|
31
|
+
# Identifies the function
|
32
|
+
# @param [Array<RDF::Term>] args
|
33
|
+
# @return [RDF::Term]
|
34
|
+
def apply(iri, *args, **options)
|
35
|
+
args = RDF.nil == args.last ? args[0..-2] : args
|
36
|
+
SPARQL::Algebra::Expression.extension(iri, *args, **options)
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Returns the SPARQL S-Expression (SSE) representation of this expression.
|
41
|
+
#
|
42
|
+
# Remove the optional argument.
|
43
|
+
#
|
44
|
+
# @return [Array] `self`
|
45
|
+
# @see https://openjena.org/wiki/SSE
|
46
|
+
def to_sxp_bin
|
47
|
+
@operands.map(&:to_sxp_bin)
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
#
|
52
|
+
# Returns a partial SPARQL grammar for this operator.
|
53
|
+
#
|
54
|
+
# @return [String]
|
55
|
+
def to_sparql(**options)
|
56
|
+
iri, args = operands
|
57
|
+
iri.to_sparql(**options) +
|
58
|
+
'(' +
|
59
|
+
args.to_sparql(delimiter: ', ', **options) +
|
60
|
+
')'
|
61
|
+
end
|
62
|
+
end # FunctionCall
|
63
|
+
end # Operator
|
64
|
+
end; end # SPARQL::Algebra
|
@@ -7,7 +7,7 @@ module SPARQL; module Algebra
|
|
7
7
|
#
|
8
8
|
# [58] GraphGraphPattern ::= 'GRAPH' VarOrIri GroupGraphPattern
|
9
9
|
#
|
10
|
-
# @example SPARQL Grammar
|
10
|
+
# @example SPARQL Grammar (query)
|
11
11
|
# PREFIX : <http://example/>
|
12
12
|
# SELECT * {
|
13
13
|
# GRAPH ?g { ?s ?p ?o }
|
@@ -18,15 +18,50 @@ module SPARQL; module Algebra
|
|
18
18
|
# (graph ?g
|
19
19
|
# (bgp (triple ?s ?p ?o))))
|
20
20
|
#
|
21
|
-
# @example of
|
21
|
+
# @example SPARQL Grammar (named set of statements)
|
22
|
+
# PREFIX : <http://example/>
|
23
|
+
# SELECT * {
|
24
|
+
# GRAPH :g { :s :p :o }
|
25
|
+
# }
|
26
|
+
#
|
27
|
+
# @example SSE (named set of statements)
|
22
28
|
# (prefix ((: <http://example/>))
|
29
|
+
# (graph :g
|
30
|
+
# (bgp (triple :s :p :o))))
|
31
|
+
#
|
32
|
+
# @example SPARQL Grammar (syntax-graph-05.rq)
|
33
|
+
# PREFIX : <http://example.org/>
|
34
|
+
# SELECT *
|
35
|
+
# WHERE
|
36
|
+
# {
|
37
|
+
# :x :p :z
|
38
|
+
# GRAPH ?g { :x :b ?a . GRAPH ?g2 { :x :p ?x } }
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# @example SSE (syntax-graph-05.rq)
|
42
|
+
# (prefix ((: <http://example.org/>))
|
43
|
+
# (join
|
44
|
+
# (bgp (triple :x :p :z))
|
23
45
|
# (graph ?g
|
24
|
-
#
|
46
|
+
# (join
|
47
|
+
# (bgp (triple :x :b ?a))
|
48
|
+
# (graph ?g2
|
49
|
+
# (bgp (triple :x :p ?x)))))))
|
25
50
|
#
|
26
|
-
# @example
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
51
|
+
# @example SPARQL Grammar (pp06.rq)
|
52
|
+
# prefix ex: <http://www.example.org/schema#>
|
53
|
+
# prefix in: <http://www.example.org/instance#>
|
54
|
+
#
|
55
|
+
# select ?x where {
|
56
|
+
# graph ?g {in:a ex:p1/ex:p2 ?x}
|
57
|
+
# }
|
58
|
+
#
|
59
|
+
# @example SSE (syntax-graph-05.rq)
|
60
|
+
# (prefix ((ex: <http://www.example.org/schema#>)
|
61
|
+
# (in: <http://www.example.org/instance#>))
|
62
|
+
# (project (?x)
|
63
|
+
# (graph ?g
|
64
|
+
# (path in:a (seq ex:p1 ex:p2) ?x))))
|
30
65
|
#
|
31
66
|
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
32
67
|
class Graph < Operator::Binary
|
@@ -89,6 +124,21 @@ module SPARQL; module Algebra
|
|
89
124
|
def rewrite(&block)
|
90
125
|
self
|
91
126
|
end
|
127
|
+
|
128
|
+
##
|
129
|
+
#
|
130
|
+
# Returns a partial SPARQL grammar for this operator.
|
131
|
+
#
|
132
|
+
# @param [Boolean] top_level (true)
|
133
|
+
# Treat this as a top-level, generating SELECT ... WHERE {}
|
134
|
+
# @return [String]
|
135
|
+
def to_sparql(top_level: true, **options)
|
136
|
+
query = operands.last.to_sparql(top_level: false, **options)
|
137
|
+
# Paths don't automatically get braces.
|
138
|
+
query = "{\n#{query}\n}" unless query.start_with?('{')
|
139
|
+
str = "GRAPH #{operands.first.to_sparql(**options)} " + query
|
140
|
+
top_level ? Operator.to_sparql(str, **options) : str
|
141
|
+
end
|
92
142
|
end # Graph
|
93
143
|
end # Operator
|
94
144
|
end; end # SPARQL::Algebra
|
@@ -25,6 +25,37 @@ module SPARQL; module Algebra
|
|
25
25
|
# (group (?P) ((??.0 (count ?O)))
|
26
26
|
# (bgp (triple ?S ?P ?O))))))
|
27
27
|
#
|
28
|
+
# @example SPARQL Grammar (HAVING aggregate)
|
29
|
+
# PREFIX : <http://www.example.org/>
|
30
|
+
# SELECT ?s (AVG(?o) AS ?avg)
|
31
|
+
# WHERE { ?s ?p ?o }
|
32
|
+
# GROUP BY ?s
|
33
|
+
# HAVING (AVG(?o) <= 2.0)
|
34
|
+
#
|
35
|
+
# @example SSE (HAVING aggregate)
|
36
|
+
# (prefix ((: <http://www.example.org/>))
|
37
|
+
# (project (?s ?avg)
|
38
|
+
# (filter (<= ??.0 2.0)
|
39
|
+
# (extend ((?avg ??.0))
|
40
|
+
# (group (?s) ((??.0 (avg ?o)))
|
41
|
+
# (bgp (triple ?s ?p ?o)))))) )
|
42
|
+
#
|
43
|
+
# @example SPARQL Grammar (non-triveal filters)
|
44
|
+
# PREFIX : <http://example.com/data/#>
|
45
|
+
# SELECT ?g (AVG(?p) AS ?avg) ((MIN(?p) + MAX(?p)) / 2 AS ?c)
|
46
|
+
# WHERE { ?g :p ?p . }
|
47
|
+
# GROUP BY ?g
|
48
|
+
#
|
49
|
+
# @example SSE (non-triveal filters)
|
50
|
+
# (prefix ((: <http://example.com/data/#>))
|
51
|
+
# (project (?g ?avg ?c)
|
52
|
+
# (extend ((?avg ??.0) (?c (/ (+ ??.1 ??.2) 2)))
|
53
|
+
# (group (?g)
|
54
|
+
# ((??.0 (avg ?p))
|
55
|
+
# (??.1 (min ?p))
|
56
|
+
# (??.2 (max ?p)))
|
57
|
+
# (bgp (triple ?g :p ?p)))) ))
|
58
|
+
#
|
28
59
|
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
29
60
|
class Group < Operator
|
30
61
|
include Query
|
@@ -137,16 +168,56 @@ module SPARQL; module Algebra
|
|
137
168
|
#
|
138
169
|
# @param [Hash{Symbol => Operator}] extensions
|
139
170
|
# Variable bindings
|
171
|
+
# @param [Array<Operator>] filter_ops ([])
|
172
|
+
# Filter Operations
|
140
173
|
# @return [String]
|
141
|
-
def to_sparql(extensions: {}, **options)
|
174
|
+
def to_sparql(extensions: {}, filter_ops: [], **options)
|
175
|
+
having_ops = []
|
142
176
|
if operands.length > 2
|
177
|
+
temp_bindings = operands[1].inject({}) {|memo, (var, op)| memo.merge(var => op)}
|
143
178
|
# Replace extensions from temporary bindings
|
144
|
-
|
145
|
-
|
146
|
-
extensions
|
179
|
+
temp_bindings.each do |var, op|
|
180
|
+
# Update extensions using a temporarily bound variable with its binding
|
181
|
+
extensions = extensions.inject({}) do |memo, (ext_var, ext_op)|
|
182
|
+
if ext_op.is_a?(Operator)
|
183
|
+
# Try to recursivley replace variable within operator
|
184
|
+
new_op = ext_op.deep_dup.rewrite do |operand|
|
185
|
+
if operand.is_a?(Variable) && operand.to_sym == var.to_sym
|
186
|
+
op.dup
|
187
|
+
else
|
188
|
+
operand
|
189
|
+
end
|
190
|
+
end
|
191
|
+
memo.merge(ext_var => new_op)
|
192
|
+
elsif ext_op.is_a?(Variable) && ext_op.to_sym == var.to_sym
|
193
|
+
memo.merge(ext_var => op)
|
194
|
+
else
|
195
|
+
# Doesn't match this variable, so don't change
|
196
|
+
memo.merge(ext_var => ext_op)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Filter ops using temporary bindinds are used for HAVING clauses
|
201
|
+
filter_ops.each do |fop|
|
202
|
+
having_ops << fop if fop.descendants.include?(var) && !having_ops.include?(fop)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# If used in a HAVING clause, it's not also a filter
|
207
|
+
filter_ops -= having_ops
|
208
|
+
|
209
|
+
# Replace each operand in having using var with it's corresponding operation
|
210
|
+
having_ops = having_ops.map do |op|
|
211
|
+
op.dup.rewrite do |operand|
|
212
|
+
# Rewrite based on temporary bindings
|
213
|
+
temp_bindings.fetch(operand, operand)
|
214
|
+
end
|
147
215
|
end
|
148
216
|
end
|
149
|
-
operands.last.to_sparql(extensions: extensions,
|
217
|
+
operands.last.to_sparql(extensions: extensions,
|
218
|
+
group_ops: operands.first,
|
219
|
+
having_ops: having_ops,
|
220
|
+
**options)
|
150
221
|
end
|
151
222
|
end # Group
|
152
223
|
end # Operator
|
@@ -16,6 +16,24 @@ module SPARQL; module Algebra
|
|
16
16
|
# (group () ((??.0 (group_concat ?x)))
|
17
17
|
# (bgp))))
|
18
18
|
#
|
19
|
+
# @example SPARQL Grammar (DISTINCT)
|
20
|
+
# SELECT (GROUP_CONCAT(DISTINCT ?x) AS ?y) {}
|
21
|
+
#
|
22
|
+
# @example SSE (DISTINCT)
|
23
|
+
# (project (?y)
|
24
|
+
# (extend ((?y ??.0))
|
25
|
+
# (group () ((??.0 (group_concat distinct ?x)))
|
26
|
+
# (bgp))))
|
27
|
+
#
|
28
|
+
# @example SPARQL Grammar (SEPARATOR)
|
29
|
+
# SELECT (GROUP_CONCAT(?x; SEPARATOR=';') AS ?y) {}
|
30
|
+
#
|
31
|
+
# @example SSE (SEPARATOR)
|
32
|
+
# (project (?y)
|
33
|
+
# (extend ((?y ??.0))
|
34
|
+
# (group () ((??.0 (group_concat (separator ";") ?x)))
|
35
|
+
# (bgp))))
|
36
|
+
#
|
19
37
|
# @see https://www.w3.org/TR/sparql11-query/#defn_aggGroupConcat
|
20
38
|
class GroupConcat < Operator
|
21
39
|
include Aggregate
|
@@ -63,7 +81,13 @@ module SPARQL; module Algebra
|
|
63
81
|
#
|
64
82
|
# @return [String]
|
65
83
|
def to_sparql(**options)
|
66
|
-
|
84
|
+
distinct = operands.first == :distinct
|
85
|
+
args = distinct ? operands[1..-1] : operands
|
86
|
+
separator = args.first.last if args.first.is_a?(Array) && args.first.first == :separator
|
87
|
+
args = args[1..-1] if separator
|
88
|
+
str = "GROUP_CONCAT(#{'DISTINCT ' if distinct}#{args.to_sparql(delimiter: ', ', **options)}"
|
89
|
+
str << "; SEPARATOR=#{separator.to_sparql}" if separator
|
90
|
+
str << ")"
|
67
91
|
end
|
68
92
|
end # GroupConcat
|
69
93
|
end # Operator
|
@@ -48,15 +48,15 @@ module SPARQL; module Algebra
|
|
48
48
|
rescue
|
49
49
|
raise TypeError
|
50
50
|
end
|
51
|
-
end # If
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
52
|
+
##
|
53
|
+
#
|
54
|
+
# Returns a partial SPARQL grammar for this operator.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
def to_sparql(**options)
|
58
|
+
"IF(" + operands.to_sparql(delimiter: ', ', **options) + ")"
|
59
|
+
end
|
60
|
+
end # If
|
61
|
+
end # Operator
|
62
62
|
end; end # SPARQL::Algebra
|
@@ -69,7 +69,9 @@ module SPARQL; module Algebra
|
|
69
69
|
#
|
70
70
|
# @return [String]
|
71
71
|
def to_sparql(**options)
|
72
|
-
"INSERT {\n" +
|
72
|
+
"INSERT {\n" +
|
73
|
+
operands.first.to_sparql(as_statement: true, delimiter: " .\n", **options) +
|
74
|
+
"\n}"
|
73
75
|
end
|
74
76
|
end # Insert
|
75
77
|
end # Operator
|
@@ -54,7 +54,7 @@ module SPARQL; module Algebra
|
|
54
54
|
# @return [String]
|
55
55
|
def to_sparql(**options)
|
56
56
|
"INSERT DATA {\n" +
|
57
|
-
operands.first.to_sparql(as_statement: true, top_level: false, delimiter: "\n", **options) +
|
57
|
+
operands.first.to_sparql(as_statement: true, top_level: false, delimiter: ". \n", **options) +
|
58
58
|
"\n}"
|
59
59
|
end
|
60
60
|
end # InsertData
|
@@ -13,8 +13,7 @@ module SPARQL; module Algebra
|
|
13
13
|
# }
|
14
14
|
#
|
15
15
|
# @example SSE
|
16
|
-
# (prefix ((
|
17
|
-
# (: <http://example.org/things#>))
|
16
|
+
# (prefix ((: <http://example.org/things#>))
|
18
17
|
# (project (?x ?v)
|
19
18
|
# (filter (isBlank ?v)
|
20
19
|
# (bgp (triple ?x :p ?v)))))
|
@@ -13,8 +13,7 @@ module SPARQL; module Algebra
|
|
13
13
|
# }
|
14
14
|
#
|
15
15
|
# @example SSE
|
16
|
-
# (prefix ((
|
17
|
-
# (: <http://example.org/things#>))
|
16
|
+
# (prefix ((: <http://example.org/things#>))
|
18
17
|
# (project (?x ?v)
|
19
18
|
# (filter (isIRI ?v)
|
20
19
|
# (bgp (triple ?x :p ?v)))))
|
@@ -13,8 +13,7 @@ module SPARQL; module Algebra
|
|
13
13
|
# }
|
14
14
|
#
|
15
15
|
# @example SSE
|
16
|
-
# (prefix ((
|
17
|
-
# (: <http://example.org/things#>))
|
16
|
+
# (prefix ((: <http://example.org/things#>))
|
18
17
|
# (project (?x ?v)
|
19
18
|
# (filter (isLiteral ?v)
|
20
19
|
# (bgp (triple ?x :p ?v)))))
|
@@ -15,8 +15,7 @@ module SPARQL; module Algebra
|
|
15
15
|
# }
|
16
16
|
#
|
17
17
|
# @example SSE
|
18
|
-
# (prefix ((
|
19
|
-
# (: <http://example.org/things#>))
|
18
|
+
# (prefix ((: <http://example.org/things#>))
|
20
19
|
# (project (?x ?v)
|
21
20
|
# (filter (isNumeric ?v)
|
22
21
|
# (bgp (triple ?x :p ?v)))))
|
@@ -19,6 +19,22 @@ module SPARQL; module Algebra
|
|
19
19
|
# (graph ?g
|
20
20
|
# (bgp (triple ?s ?q ?v)))))
|
21
21
|
#
|
22
|
+
# @example SPARQL Grammar (inline filter)
|
23
|
+
# PREFIX : <http://xmlns.com/foaf/0.1/>
|
24
|
+
# ASK {
|
25
|
+
# :who :homepage ?homepage
|
26
|
+
# FILTER REGEX(?homepage, "^http://example.org/")
|
27
|
+
# :who :schoolHomepage ?schoolPage
|
28
|
+
# }
|
29
|
+
#
|
30
|
+
# @example SSE (inline filter)
|
31
|
+
# (prefix ((: <http://xmlns.com/foaf/0.1/>))
|
32
|
+
# (ask
|
33
|
+
# (filter (regex ?homepage "^http://example.org/")
|
34
|
+
# (join
|
35
|
+
# (bgp (triple :who :homepage ?homepage))
|
36
|
+
# (bgp (triple :who :schoolHomepage ?schoolPage))))))
|
37
|
+
#
|
22
38
|
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
23
39
|
class Join < Operator::Binary
|
24
40
|
include Query
|
@@ -98,10 +114,28 @@ module SPARQL; module Algebra
|
|
98
114
|
#
|
99
115
|
# @param [Boolean] top_level (true)
|
100
116
|
# Treat this as a top-level, generating SELECT ... WHERE {}
|
117
|
+
# @param [Hash{Symbol => Operator}] extensions
|
118
|
+
# Variable bindings
|
119
|
+
# @param [Array<Operator>] filter_ops ([])
|
120
|
+
# Filter Operations
|
101
121
|
# @return [String]
|
102
|
-
def to_sparql(top_level: true, **options)
|
103
|
-
|
104
|
-
|
122
|
+
def to_sparql(top_level: true, filter_ops: [], extensions: {}, **options)
|
123
|
+
# If this is top-level, and the last operand is a Table (values), put the values at the outer-level
|
124
|
+
str = "{\n" + operands.first.to_sparql(top_level: false, extensions: {}, **options)
|
125
|
+
|
126
|
+
# Any accrued filters go here.
|
127
|
+
filter_ops.each do |op|
|
128
|
+
str << "\nFILTER (#{op.to_sparql(**options)}) ."
|
129
|
+
end
|
130
|
+
|
131
|
+
if top_level && operands.last.is_a?(Table)
|
132
|
+
str << "\n}"
|
133
|
+
options = options.merge(values_clause: operands.last)
|
134
|
+
else
|
135
|
+
str << "\n{\n" + operands.last.to_sparql(top_level: false, extensions: {}, **options) + "\n}\n}"
|
136
|
+
end
|
137
|
+
|
138
|
+
top_level ? Operator.to_sparql(str, extensions: extensions, **options) : str
|
105
139
|
end
|
106
140
|
end # Join
|
107
141
|
end # Operator
|
@@ -12,9 +12,8 @@ module SPARQL; module Algebra
|
|
12
12
|
# }
|
13
13
|
#
|
14
14
|
# @example SSE
|
15
|
-
# (prefix
|
16
|
-
# ((
|
17
|
-
# (project (?str ?lstr)
|
15
|
+
# (prefix ((: <http://example.org/>))
|
16
|
+
# (project (?s ?lstr)
|
18
17
|
# (extend ((?lstr (lcase ?str)))
|
19
18
|
# (bgp (triple ?s :str ?str)))))
|
20
19
|
#
|
@@ -131,14 +131,27 @@ module SPARQL; module Algebra
|
|
131
131
|
#
|
132
132
|
# @param [Boolean] top_level (true)
|
133
133
|
# Treat this as a top-level, generating SELECT ... WHERE {}
|
134
|
+
# @param [Hash{Symbol => Operator}] extensions
|
135
|
+
# Variable bindings
|
136
|
+
# @param [Array<Operator>] filter_ops ([])
|
137
|
+
# Filter Operations
|
134
138
|
# @return [String]
|
135
|
-
def to_sparql(top_level: true, **options)
|
136
|
-
str = operands[0].to_sparql(top_level: false, **options)
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
139
|
+
def to_sparql(top_level: true, filter_ops: [], extensions: {}, **options)
|
140
|
+
str = "{\n" + operands[0].to_sparql(top_level: false, extensions: {}, **options)
|
141
|
+
str <<
|
142
|
+
"\nOPTIONAL {\n" +
|
143
|
+
operands[1].to_sparql(top_level: false, extensions: {}, **options)
|
144
|
+
case operands[2]
|
145
|
+
when SPARQL::Algebra::Operator::Exprlist
|
146
|
+
operands[2].operands.each do |op|
|
147
|
+
str << "\nFILTER (" + op.to_sparql(**options) + ")"
|
148
|
+
end
|
149
|
+
when nil
|
150
|
+
else
|
151
|
+
str << "\nFILTER (" + operands[2].to_sparql(**options) + ")"
|
152
|
+
end
|
153
|
+
str << "\n}}"
|
154
|
+
top_level ? Operator.to_sparql(str, filter_ops: filter_ops, extensions: extensions, **options) : str
|
142
155
|
end
|
143
156
|
end # LeftJoin
|
144
157
|
end # Operator
|
@@ -56,7 +56,9 @@ module SPARQL; module Algebra
|
|
56
56
|
#
|
57
57
|
# @return [String]
|
58
58
|
def to_sparql(**options)
|
59
|
-
|
59
|
+
distinct = operands.first == :distinct
|
60
|
+
args = distinct ? operands[1..-1] : operands
|
61
|
+
"MAX(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
|
60
62
|
end
|
61
63
|
end # Max
|
62
64
|
end # Operator
|
@@ -15,7 +15,7 @@ module SPARQL; module Algebra
|
|
15
15
|
# (project (?min)
|
16
16
|
# (extend ((?min ??.0))
|
17
17
|
# (group () ((??.0 (min ?o)))
|
18
|
-
# (bgp (triple ?s
|
18
|
+
# (bgp (triple ?s :dec ?o))))))
|
19
19
|
#
|
20
20
|
# @see https://www.w3.org/TR/sparql11-query/#defn_aggMin
|
21
21
|
class Min < Operator
|
@@ -56,7 +56,9 @@ module SPARQL; module Algebra
|
|
56
56
|
#
|
57
57
|
# @return [String]
|
58
58
|
def to_sparql(**options)
|
59
|
-
|
59
|
+
distinct = operands.first == :distinct
|
60
|
+
args = distinct ? operands[1..-1] : operands
|
61
|
+
"MIN(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
|
60
62
|
end
|
61
63
|
end # Min
|
62
64
|
end # Operator
|
@@ -14,6 +14,32 @@ module SPARQL; module Algebra
|
|
14
14
|
# (triple ?s ?p ?o))
|
15
15
|
# (bgp (triple ?s ?q ?v)))
|
16
16
|
#
|
17
|
+
# @example SPARQL Grammar (inline filter)
|
18
|
+
# PREFIX : <http://example/>
|
19
|
+
# SELECT (?s1 AS ?subset) (?s2 AS ?superset)
|
20
|
+
# WHERE {
|
21
|
+
# ?s2 a :Set .
|
22
|
+
# ?s1 a :Set .
|
23
|
+
# FILTER(?s1 != ?s2)
|
24
|
+
# MINUS {
|
25
|
+
# ?s1 a :Set .
|
26
|
+
# ?s2 a :Set .
|
27
|
+
# FILTER(?s1 != ?s2)
|
28
|
+
# }
|
29
|
+
# }
|
30
|
+
#
|
31
|
+
# @example SSE (inline filter)
|
32
|
+
# (prefix ((: <http://example/>))
|
33
|
+
# (project (?subset ?superset)
|
34
|
+
# (extend ((?subset ?s1) (?superset ?s2))
|
35
|
+
# (filter (!= ?s1 ?s2)
|
36
|
+
# (minus
|
37
|
+
# (bgp (triple ?s2 a :Set) (triple ?s1 a :Set))
|
38
|
+
# (filter (!= ?s1 ?s2)
|
39
|
+
# (bgp
|
40
|
+
# (triple ?s1 a :Set)
|
41
|
+
# (triple ?s2 a :Set))))))))
|
42
|
+
#
|
17
43
|
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-unary-minus
|
18
44
|
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
19
45
|
class Minus < Operator::Binary
|
@@ -74,15 +100,29 @@ module SPARQL; module Algebra
|
|
74
100
|
#
|
75
101
|
# Returns a partial SPARQL grammar for this operator.
|
76
102
|
#
|
103
|
+
# @param [Hash{Symbol => Operator}] extensions
|
104
|
+
# Variable bindings
|
105
|
+
# @param [Array<Operator>] filter_ops ([])
|
106
|
+
# Filter Operations
|
77
107
|
# @param [Boolean] top_level (true)
|
78
108
|
# Treat this as a top-level, generating SELECT ... WHERE {}
|
79
109
|
# @return [String]
|
80
|
-
def to_sparql(top_level: true, **options)
|
81
|
-
|
82
|
-
str
|
83
|
-
|
84
|
-
|
85
|
-
|
110
|
+
def to_sparql(top_level: true, filter_ops: [], extensions: {}, **options)
|
111
|
+
lhs, *rhs = operands
|
112
|
+
str = "{\n" + lhs.to_sparql(top_level: false, extensions: {}, **options)
|
113
|
+
|
114
|
+
# Any accrued filters go here.
|
115
|
+
filter_ops.each do |op|
|
116
|
+
str << "\nFILTER (#{op.to_sparql(**options)}) ."
|
117
|
+
end
|
118
|
+
|
119
|
+
rhs.each do |minus|
|
120
|
+
str << "\nMINUS {\n"
|
121
|
+
str << minus.to_sparql(top_level: false, extensions: {}, **options)
|
122
|
+
str << "\n}"
|
123
|
+
end
|
124
|
+
str << "}"
|
125
|
+
top_level ? Operator.to_sparql(str, extensions: extensions, **options) : str
|
86
126
|
end
|
87
127
|
end # Minus
|
88
128
|
end # Operator
|
@@ -50,7 +50,7 @@ module SPARQL; module Algebra
|
|
50
50
|
#
|
51
51
|
# @return [String]
|
52
52
|
def to_sparql(**options)
|
53
|
-
"#{operands.first.to_sparql(**options)} * #{operands.last.to_sparql(**options)}"
|
53
|
+
"(#{operands.first.to_sparql(**options)} * #{operands.last.to_sparql(**options)})"
|
54
54
|
end
|
55
55
|
end # Multiply
|
56
56
|
end # Operator
|
@@ -8,13 +8,13 @@ module SPARQL; module Algebra
|
|
8
8
|
# @example SPARQL Grammar
|
9
9
|
# PREFIX ex: <http://www.example.org/schema#>
|
10
10
|
# PREFIX in: <http://www.example.org/instance#>
|
11
|
-
# ASK { in:
|
11
|
+
# ASK { in:a !(ex:p1|ex:p2) ?x }
|
12
12
|
#
|
13
13
|
# @example SSE
|
14
14
|
# (prefix ((ex: <http://www.example.org/schema#>)
|
15
|
-
#
|
15
|
+
# (in: <http://www.example.org/instance#>))
|
16
16
|
# (ask
|
17
|
-
# (path in:
|
17
|
+
# (path in:a (notoneof ex:p1 ex:p2) ?x)))
|
18
18
|
#
|
19
19
|
# @see https://www.w3.org/TR/sparql11-query/#eval_negatedPropertySet
|
20
20
|
class NotOneOf < Operator
|
@@ -56,6 +56,15 @@ module SPARQL; module Algebra
|
|
56
56
|
block.call(solution)
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
##
|
61
|
+
#
|
62
|
+
# Returns a partial SPARQL grammar for this operator.
|
63
|
+
#
|
64
|
+
# @return [String]
|
65
|
+
def to_sparql(**options)
|
66
|
+
"!(" + operands.to_sparql(delimiter: ' | ', **options) + ')'
|
67
|
+
end
|
59
68
|
end # NotOneOf
|
60
69
|
end # Operator
|
61
70
|
end; end # SPARQL::Algebra
|