sparql 3.2.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
@@ -17,6 +17,50 @@ module SPARQL; module Algebra
|
|
17
17
|
# (order ((asc ?name))
|
18
18
|
# (bgp (triple ?x foaf:name ?name)))))
|
19
19
|
#
|
20
|
+
# @example SPARQL Grammar (with builtin)
|
21
|
+
# PREFIX : <http://example.org/>
|
22
|
+
# SELECT ?s WHERE {
|
23
|
+
# ?s :p ?o .
|
24
|
+
# }
|
25
|
+
# ORDER BY str(?o)
|
26
|
+
#
|
27
|
+
# @example SSE (with builtin)
|
28
|
+
# (prefix ((: <http://example.org/>))
|
29
|
+
# (project (?s)
|
30
|
+
# (order ((str ?o))
|
31
|
+
# (bgp (triple ?s :p ?o)))))
|
32
|
+
#
|
33
|
+
# @example SPARQL Grammar (with bracketed expression)
|
34
|
+
# PREFIX : <http://example.org/>
|
35
|
+
# SELECT ?s WHERE {
|
36
|
+
# ?s :p ?o1 ; :q ?o2 .
|
37
|
+
# } ORDER BY (?o1 + ?o2)
|
38
|
+
#
|
39
|
+
# @example SSE (with bracketed expression)
|
40
|
+
# (prefix
|
41
|
+
# ((: <http://example.org/>))
|
42
|
+
# (project (?s)
|
43
|
+
# (order ((+ ?o1 ?o2))
|
44
|
+
# (bgp
|
45
|
+
# (triple ?s :p ?o1)
|
46
|
+
# (triple ?s :q ?o2)))))
|
47
|
+
#
|
48
|
+
# @example SPARQL Grammar (with function call)
|
49
|
+
# PREFIX : <http://example.org/ns#>
|
50
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
51
|
+
# SELECT *
|
52
|
+
# { ?s ?p ?o }
|
53
|
+
# ORDER BY
|
54
|
+
# DESC(?o+57) xsd:string(?o) ASC(?s)
|
55
|
+
#
|
56
|
+
# @example SSE (with function call)
|
57
|
+
# (prefix ((: <http://example.org/ns#>)
|
58
|
+
# (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
59
|
+
# (order ((desc (+ ?o 57))
|
60
|
+
# (xsd:string ?o)
|
61
|
+
# (asc ?s))
|
62
|
+
# (bgp (triple ?s ?p ?o))))
|
63
|
+
#
|
20
64
|
# @see https://www.w3.org/TR/sparql11-query/#modOrderBy
|
21
65
|
class Order < Operator::Binary
|
22
66
|
include Query
|
@@ -69,7 +69,7 @@ module SPARQL; module Algebra
|
|
69
69
|
#
|
70
70
|
# @return [String]
|
71
71
|
def to_sparql(**options)
|
72
|
-
"#{operands.first.to_sparql(**options)} + #{operands.last.to_sparql(**options)}"
|
72
|
+
"(#{operands.first.to_sparql(**options)} + #{operands.last.to_sparql(**options)})"
|
73
73
|
end
|
74
74
|
end # Plus
|
75
75
|
end # Operator
|
@@ -20,20 +20,37 @@ module SPARQL; module Algebra
|
|
20
20
|
# (filter (= ?v 2)
|
21
21
|
# (bgp (triple ?s :p ?v)))))
|
22
22
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# @example SPARQL Grammar
|
23
|
+
# @example SPARQL Grammar (Sub select)
|
26
24
|
# SELECT (1 AS ?X ) {
|
27
25
|
# SELECT (2 AS ?Y ) {}
|
28
26
|
# }
|
29
27
|
#
|
30
|
-
# @example SSE
|
28
|
+
# @example SSE (Sub select)
|
31
29
|
# (project (?X)
|
32
30
|
# (extend ((?X 1))
|
33
31
|
# (project (?Y)
|
34
32
|
# (extend ((?Y 2))
|
35
33
|
# (bgp)))))
|
36
34
|
#
|
35
|
+
# @example SPARQL Grammar (filter projection)
|
36
|
+
# PREFIX : <http://www.example.org/>
|
37
|
+
# ASK {
|
38
|
+
# {SELECT (GROUP_CONCAT(?o) AS ?g) WHERE {
|
39
|
+
# :a :p1 ?o
|
40
|
+
# }}
|
41
|
+
# FILTER(?g = "1 22" || ?g = "22 1")
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# @example SSE (filter projection)
|
45
|
+
# (prefix ((: <http://www.example.org/>))
|
46
|
+
# (ask
|
47
|
+
# (filter
|
48
|
+
# (|| (= ?g "1 22") (= ?g "22 1"))
|
49
|
+
# (project (?g)
|
50
|
+
# (extend ((?g ??.0))
|
51
|
+
# (group () ((??.0 (group_concat ?o)))
|
52
|
+
# (bgp (triple :a :p1 ?o)))))) ))
|
53
|
+
#
|
37
54
|
# @see https://www.w3.org/TR/sparql11-query/#modProjection
|
38
55
|
class Project < Operator::Binary
|
39
56
|
include Query
|
@@ -77,6 +94,7 @@ module SPARQL; module Algebra
|
|
77
94
|
# Any of these options indicates we're in a sub-select
|
78
95
|
opts = options.dup.delete_if {|k,v| %I{extensions filter_ops project}.include?(k)}
|
79
96
|
content = operands.last.to_sparql(project: vars, **opts)
|
97
|
+
content = "{#{content}}" unless content.start_with?('{') && content.end_with?('}')
|
80
98
|
Operator.to_sparql(content, **options)
|
81
99
|
else
|
82
100
|
operands.last.to_sparql(project: vars, **options)
|
@@ -8,12 +8,12 @@ module SPARQL; module Algebra
|
|
8
8
|
# @example SPARQL Grammar
|
9
9
|
# PREFIX : <http://example.org/>
|
10
10
|
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
11
|
-
# SELECT
|
11
|
+
# SELECT REDUCED ?v
|
12
12
|
# WHERE { ?x ?p ?v }
|
13
13
|
#
|
14
14
|
# @example SSE
|
15
|
-
# (prefix ((
|
16
|
-
# (: <http://
|
15
|
+
# (prefix ((: <http://example.org/>)
|
16
|
+
# (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
17
17
|
# (reduced
|
18
18
|
# (project (?v)
|
19
19
|
# (bgp (triple ?x ?p ?v)))))
|
@@ -6,8 +6,8 @@ module SPARQL; module Algebra
|
|
6
6
|
# [122] RegexExpression ::= 'REGEX' '(' Expression ',' Expression ( ',' Expression )? ')'
|
7
7
|
#
|
8
8
|
# @example SPARQL Grammar
|
9
|
-
# PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
10
9
|
# PREFIX ex: <http://example.com/#>
|
10
|
+
# PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
11
11
|
# SELECT ?val
|
12
12
|
# WHERE {
|
13
13
|
# ex:foo rdf:value ?val .
|
@@ -15,6 +15,17 @@ module SPARQL; module Algebra
|
|
15
15
|
# (in: <http://www.example.org/instance#>))
|
16
16
|
# (ask (path in:b (reverse ex:p) in:a)))
|
17
17
|
#
|
18
|
+
# @example SPARQL Grammar
|
19
|
+
# prefix ex: <http://www.example.org/schema#>
|
20
|
+
# prefix in: <http://www.example.org/instance#>
|
21
|
+
#
|
22
|
+
# select * where { in:c ^(ex:p1/ex:p2) ?x }
|
23
|
+
#
|
24
|
+
# @example SSE
|
25
|
+
# (prefix ((ex: <http://www.example.org/schema#>)
|
26
|
+
# (in: <http://www.example.org/instance#>))
|
27
|
+
# (path in:c (reverse (seq ex:p1 ex:p2)) ?x))
|
28
|
+
#
|
18
29
|
# @see https://www.w3.org/TR/sparql11-query/#defn_evalPP_inverse
|
19
30
|
class Reverse < Operator::Unary
|
20
31
|
include Query
|
@@ -65,7 +76,7 @@ module SPARQL; module Algebra
|
|
65
76
|
#
|
66
77
|
# @return [String]
|
67
78
|
def to_sparql(**options)
|
68
|
-
"^" + operands.first.to_sparql(**options)
|
79
|
+
"^(" + operands.first.to_sparql(**options) + ')'
|
69
80
|
end
|
70
81
|
end # Reverse
|
71
82
|
end # Operator
|
@@ -54,7 +54,9 @@ module SPARQL; module Algebra
|
|
54
54
|
#
|
55
55
|
# @return [String]
|
56
56
|
def to_sparql(**options)
|
57
|
-
|
57
|
+
distinct = operands.first == :distinct
|
58
|
+
args = distinct ? operands[1..-1] : operands
|
59
|
+
"SAMPLE(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
|
58
60
|
end
|
59
61
|
end # Sample
|
60
62
|
end # Operator
|
@@ -4,8 +4,11 @@ module SPARQL; module Algebra
|
|
4
4
|
##
|
5
5
|
# The SPARQL UPDATE `sequence` operator.
|
6
6
|
#
|
7
|
-
# Sequences through each operand
|
7
|
+
# Sequences through each operand.
|
8
8
|
#
|
9
|
+
# [103] CollectionPath ::= '(' GraphNodePath+ ')'
|
10
|
+
#
|
11
|
+
# @see https://www.w3.org/TR/sparql11-query/#collections
|
9
12
|
class Sequence < Operator
|
10
13
|
include SPARQL::Algebra::Update
|
11
14
|
|
@@ -13,8 +13,7 @@ module SPARQL; module Algebra
|
|
13
13
|
# }
|
14
14
|
#
|
15
15
|
# @example SSE
|
16
|
-
# (prefix
|
17
|
-
# ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
16
|
+
# (prefix ((: <http://example.org/>))
|
18
17
|
# (project (?s ?s2)
|
19
18
|
# (extend ((?s2 (strlang ?str "en-US")))
|
20
19
|
# (filter (langMatches (lang ?str) "en")
|
@@ -51,7 +51,7 @@ module SPARQL; module Algebra
|
|
51
51
|
#
|
52
52
|
# @return [String]
|
53
53
|
def to_sparql(**options)
|
54
|
-
"#{operands.first.to_sparql(**options)} - #{operands.last.to_sparql(**options)}"
|
54
|
+
"(#{operands.first.to_sparql(**options)} - #{operands.last.to_sparql(**options)})"
|
55
55
|
end
|
56
56
|
end # Subtract
|
57
57
|
end # Operator
|
@@ -7,15 +7,15 @@ module SPARQL; module Algebra
|
|
7
7
|
#
|
8
8
|
# @example SPARQL Grammar
|
9
9
|
# PREFIX : <http://www.example.org/>
|
10
|
-
# SELECT (SUM(?
|
10
|
+
# SELECT (SUM(?o) AS ?sum)
|
11
11
|
# WHERE { ?s :dec ?o }
|
12
12
|
#
|
13
13
|
# @example SSE
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# (prefix ((: <http://www.example.org/>))
|
15
|
+
# (project (?sum)
|
16
|
+
# (extend ((?sum ??.0))
|
17
|
+
# (group () ((??.0 (sum ?o)))
|
18
|
+
# (bgp (triple ?s :dec ?o))))))
|
19
19
|
#
|
20
20
|
# @see https://www.w3.org/TR/sparql11-query/#defn_aggSum
|
21
21
|
class Sum < Operator
|
@@ -47,7 +47,9 @@ module SPARQL; module Algebra
|
|
47
47
|
#
|
48
48
|
# @return [String]
|
49
49
|
def to_sparql(**options)
|
50
|
-
|
50
|
+
distinct = operands.first == :distinct
|
51
|
+
args = distinct ? operands[1..-1] : operands
|
52
|
+
"SUM(#{'DISTINCT ' if distinct}#{args.to_sparql(**options)})"
|
51
53
|
end
|
52
54
|
end # Sum
|
53
55
|
end # Operator
|
@@ -8,7 +8,7 @@ module SPARQL; module Algebra
|
|
8
8
|
#
|
9
9
|
# [28] ValuesClause ::= ( 'VALUES' DataBlock )?
|
10
10
|
#
|
11
|
-
# @example SPARQL Grammar
|
11
|
+
# @example SPARQL Grammar (ValuesClause)
|
12
12
|
# PREFIX dc: <http://purl.org/dc/elements/1.1/>
|
13
13
|
# PREFIX : <http://example.org/book/>
|
14
14
|
# PREFIX ns: <http://example.org/ns#>
|
@@ -18,7 +18,7 @@ module SPARQL; module Algebra
|
|
18
18
|
# }
|
19
19
|
# VALUES ?book { :book1 }
|
20
20
|
#
|
21
|
-
# @example SSE
|
21
|
+
# @example SSE (ValuesClause)
|
22
22
|
# (prefix ((dc: <http://purl.org/dc/elements/1.1/>)
|
23
23
|
# (: <http://example.org/book/>)
|
24
24
|
# (ns: <http://example.org/ns#>))
|
@@ -27,8 +27,38 @@ module SPARQL; module Algebra
|
|
27
27
|
# (bgp (triple ?book dc:title ?title) (triple ?book ns:price ?price))
|
28
28
|
# (table (vars ?book) (row (?book :book1)))) ))
|
29
29
|
#
|
30
|
+
# @example SPARQL Grammar (empty query no values)
|
31
|
+
# SELECT * { } VALUES () { }
|
32
|
+
#
|
33
|
+
# @example SSE (empty query no values)
|
34
|
+
# (join (bgp) (table empty))
|
35
|
+
#
|
36
|
+
# [61] InlineData ::= 'VALUES' DataBlock
|
37
|
+
#
|
38
|
+
# @example SPARQL Grammar (InlineData)
|
39
|
+
# PREFIX dc: <http://purl.org/dc/elements/1.1/>
|
40
|
+
# PREFIX : <http://example.org/book/>
|
41
|
+
# PREFIX ns: <http://example.org/ns#>
|
42
|
+
#
|
43
|
+
# SELECT ?book ?title ?price
|
44
|
+
# {
|
45
|
+
# VALUES ?book { :book1 }
|
46
|
+
# ?book dc:title ?title ;
|
47
|
+
# ns:price ?price .
|
48
|
+
# }
|
49
|
+
#
|
50
|
+
# @example SSE (InlineData)
|
51
|
+
# (prefix ((dc: <http://purl.org/dc/elements/1.1/>)
|
52
|
+
# (: <http://example.org/book/>)
|
53
|
+
# (ns: <http://example.org/ns#>))
|
54
|
+
# (project (?book ?title ?price)
|
55
|
+
# (join
|
56
|
+
# (table (vars ?book) (row (?book :book1)))
|
57
|
+
# (bgp (triple ?book dc:title ?title) (triple ?book ns:price ?price))) ))
|
58
|
+
#
|
30
59
|
# @example empty table
|
31
60
|
# (table unit)
|
61
|
+
#
|
32
62
|
# @see https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#inline-data
|
33
63
|
class Table < Operator
|
34
64
|
include Query
|
@@ -67,22 +97,26 @@ module SPARQL; module Algebra
|
|
67
97
|
#
|
68
98
|
# Returns a partial SPARQL grammar for this operator.
|
69
99
|
#
|
100
|
+
# @param [Boolean] top_level (true)
|
101
|
+
# Treat this as a top-level, generating SELECT ... WHERE {}
|
70
102
|
# @return [String]
|
71
|
-
def to_sparql(**options)
|
72
|
-
str = "VALUES (#{operands.first[1..-1].map { |e| e.to_sparql(**options) }.join(' ')}) {\n"
|
103
|
+
def to_sparql(top_level: true, **options)
|
104
|
+
str = "VALUES (#{Array(operands.first)[1..-1].map { |e| e.to_sparql(**options) }.join(' ')}) {\n"
|
73
105
|
operands[1..-1].each do |row|
|
74
106
|
line = '('
|
75
107
|
row[1..-1].each do |col|
|
76
|
-
|
108
|
+
v = col[1].to_sparql(as_statement: true, **options)
|
109
|
+
v = "<< #{v} >>" if col[1].is_a?(RDF::Statement)
|
110
|
+
line << v + ' '
|
77
111
|
end
|
78
|
-
line = line.
|
112
|
+
line = line.chomp(' ')
|
79
113
|
line << ")\n"
|
80
114
|
|
81
115
|
str << line
|
82
116
|
end
|
83
117
|
|
84
118
|
str << "}\n"
|
85
|
-
str
|
119
|
+
top_level ? Operator.to_sparql(str, **options) : str
|
86
120
|
end
|
87
121
|
end # Table
|
88
122
|
end # Operator
|
@@ -21,6 +21,27 @@ module SPARQL; module Algebra
|
|
21
21
|
# (delete ((triple ?a foaf:knows ?b)))
|
22
22
|
# (insert ((triple ?b foaf:knows ?a)))) ))
|
23
23
|
#
|
24
|
+
# @example SPARQL Grammar (update multiple)
|
25
|
+
# PREFIX : <http://example.org/>
|
26
|
+
# PREFIX foaf: <http://xmlns.com/foaf/0.1/>
|
27
|
+
#
|
28
|
+
# DELETE { ?a foaf:knows ?b . }
|
29
|
+
# WHERE { ?a foaf:knows ?b . }
|
30
|
+
# ;
|
31
|
+
# INSERT { ?b foaf:knows ?a . }
|
32
|
+
# WHERE { ?a foaf:knows ?b .}
|
33
|
+
#
|
34
|
+
# @example SSE (update multiple)
|
35
|
+
# (prefix ((: <http://example.org/>)
|
36
|
+
# (foaf: <http://xmlns.com/foaf/0.1/>))
|
37
|
+
# (update
|
38
|
+
# (modify
|
39
|
+
# (bgp (triple ?a foaf:knows ?b))
|
40
|
+
# (delete ((triple ?a foaf:knows ?b))))
|
41
|
+
# (modify
|
42
|
+
# (bgp (triple ?a foaf:knows ?b))
|
43
|
+
# (insert ((triple ?b foaf:knows ?a))))))
|
44
|
+
#
|
24
45
|
# @see https://www.w3.org/TR/sparql11-update/#graphUpdate
|
25
46
|
class Update < Operator
|
26
47
|
include SPARQL::Algebra::Update
|
@@ -58,7 +79,7 @@ module SPARQL; module Algebra
|
|
58
79
|
#
|
59
80
|
# @return [String]
|
60
81
|
def to_sparql(**options)
|
61
|
-
str = operands.map { |e| e.to_sparql(**options) }.join("
|
82
|
+
str = operands.map { |e| e.to_sparql(**options) }.join(";\n")
|
62
83
|
end
|
63
84
|
end # Update
|
64
85
|
end # Operator
|
@@ -28,6 +28,21 @@ module SPARQL; module Algebra
|
|
28
28
|
# (bgp (triple :a foaf:knows ?s) (triple ?s ?p ?o)))
|
29
29
|
# (delete ((triple ?s ?p ?o)))) ))
|
30
30
|
#
|
31
|
+
# @example SPARQL Grammar (multiple clauses)
|
32
|
+
# PREFIX : <http://example.org/>
|
33
|
+
#
|
34
|
+
# INSERT { ?s ?p "q" }
|
35
|
+
# USING :g1
|
36
|
+
# USING :g2
|
37
|
+
# WHERE { ?s ?p ?o }
|
38
|
+
#
|
39
|
+
# @example SSE (multiple clauses)
|
40
|
+
# (prefix ((: <http://example.org/>))
|
41
|
+
# (update
|
42
|
+
# (modify (using (:g1 :g2)
|
43
|
+
# (bgp (triple ?s ?p ?o)))
|
44
|
+
# (insert ((triple ?s ?p "q"))))))
|
45
|
+
#
|
31
46
|
# @see https://www.w3.org/TR/sparql11-update/#add
|
32
47
|
class Using < Operator
|
33
48
|
include SPARQL::Algebra::Query
|
@@ -61,7 +76,9 @@ module SPARQL; module Algebra
|
|
61
76
|
#
|
62
77
|
# @return [String]
|
63
78
|
def to_sparql(**options)
|
64
|
-
str = "
|
79
|
+
str = "\n" + operands.first.map do |op|
|
80
|
+
"USING #{op.to_sparql(**options)}\n"
|
81
|
+
end.join("")
|
65
82
|
content = operands.last.to_sparql(top_level: false, **options)
|
66
83
|
str << Operator.to_sparql(content, project: nil, **options)
|
67
84
|
end
|
@@ -106,6 +106,7 @@ module SPARQL; module Algebra
|
|
106
106
|
autoload :Coalesce, 'sparql/algebra/operator/coalesce'
|
107
107
|
autoload :Desc, 'sparql/algebra/operator/desc'
|
108
108
|
autoload :Exprlist, 'sparql/algebra/operator/exprlist'
|
109
|
+
autoload :FunctionCall, 'sparql/algebra/operator/function_call'
|
109
110
|
autoload :GroupConcat, 'sparql/algebra/operator/group_concat'
|
110
111
|
autoload :In, 'sparql/algebra/operator/in'
|
111
112
|
autoload :NotIn, 'sparql/algebra/operator/notin'
|
@@ -254,6 +255,7 @@ module SPARQL; module Algebra
|
|
254
255
|
when :asc then Asc
|
255
256
|
when :desc then Desc
|
256
257
|
when :exprlist then Exprlist
|
258
|
+
when :function_call then FunctionCall
|
257
259
|
|
258
260
|
# Datasets
|
259
261
|
when :dataset then Dataset
|
@@ -336,31 +338,41 @@ module SPARQL; module Algebra
|
|
336
338
|
# Generate a top-level Grammar, using collected options
|
337
339
|
#
|
338
340
|
# @param [String] content
|
341
|
+
# @param [Operator] datasets ([])
|
342
|
+
# @param [Operator] distinct (false)
|
339
343
|
# @param [Hash{Symbol => Operator}] extensions
|
340
344
|
# Variable bindings
|
341
|
-
# @param [Operator] distinct (false)
|
342
345
|
# @param [Array<Operator>] filter_ops ([])
|
343
346
|
# Filter Operations
|
344
347
|
# @param [Integer] limit (nil)
|
345
348
|
# @param [Array<Operator>] group_ops ([])
|
349
|
+
# @param [Array<Operator>] having_ops ([])
|
346
350
|
# @param [Integer] offset (nil)
|
347
351
|
# @param [Array<Operator>] order_ops ([])
|
348
352
|
# Order Operations
|
349
353
|
# @param [Array<Symbol,Operator>] project (%i(*))
|
350
354
|
# Terms to project
|
351
355
|
# @param [Operator] reduced (false)
|
356
|
+
# @param [Operator] values_clause (nil)
|
357
|
+
# Top-level Values clause
|
358
|
+
# @param [Operator] where_clause (true)
|
359
|
+
# Emit 'WHERE' before GroupGraphPattern
|
352
360
|
# @param [Hash{Symbol => Object}] options
|
353
361
|
# @return [String]
|
354
362
|
def self.to_sparql(content,
|
363
|
+
datasets: [],
|
355
364
|
distinct: false,
|
356
365
|
extensions: {},
|
357
366
|
filter_ops: [],
|
358
367
|
group_ops: [],
|
368
|
+
having_ops: [],
|
359
369
|
limit: nil,
|
360
370
|
offset: nil,
|
361
371
|
order_ops: [],
|
362
372
|
project: %i(*),
|
363
373
|
reduced: false,
|
374
|
+
values_clause: nil,
|
375
|
+
where_clause: true,
|
364
376
|
**options)
|
365
377
|
str = ""
|
366
378
|
|
@@ -372,28 +384,41 @@ module SPARQL; module Algebra
|
|
372
384
|
|
373
385
|
str << project.map do |p|
|
374
386
|
if expr = extensions.delete(p)
|
387
|
+
v = expr.to_sparql(as_statement: true, **options)
|
388
|
+
v = "<< #{v} >>" if expr.is_a?(RDF::Statement)
|
389
|
+
pp = p.to_sparql(**options)
|
375
390
|
# Replace projected variables with their extension, if any
|
376
|
-
|
391
|
+
'(' + v + ' AS ' + pp + ')'
|
377
392
|
else
|
378
393
|
p.to_sparql(**options)
|
379
394
|
end
|
380
395
|
end.join(" ") + "\n"
|
381
396
|
end
|
382
397
|
|
383
|
-
#
|
398
|
+
# DatasetClause
|
399
|
+
datasets.each do |ds|
|
400
|
+
str << "FROM #{ds.to_sparql(**options)}\n"
|
401
|
+
end
|
402
|
+
|
403
|
+
# Bind
|
384
404
|
extensions.each do |as, expression|
|
385
|
-
|
405
|
+
v = expression.to_sparql(as_statement: true, **options)
|
406
|
+
v = "<< #{v} >>" if expression.is_a?(RDF::Statement)
|
407
|
+
content << "\nBIND (" << v << " AS " << as.to_sparql(**options) << ") ."
|
386
408
|
end
|
387
409
|
|
388
|
-
#
|
410
|
+
# Filter
|
389
411
|
filter_ops.each do |f|
|
390
|
-
content << "\nFILTER #{f.to_sparql(**options)} ."
|
412
|
+
content << "\nFILTER (#{f.to_sparql(**options)}) ."
|
391
413
|
end
|
392
414
|
|
393
|
-
#
|
394
|
-
str << "WHERE {\n#{content}\n}\n"
|
415
|
+
# WhereClause / GroupGraphPattern
|
416
|
+
str << (where_clause ? "WHERE {\n#{content}\n}\n" : "{\n#{content}\n}\n")
|
395
417
|
|
396
|
-
|
418
|
+
##
|
419
|
+
# SolutionModifier
|
420
|
+
#
|
421
|
+
# GroupClause
|
397
422
|
unless group_ops.empty?
|
398
423
|
ops = group_ops.map do |o|
|
399
424
|
# Replace projected variables with their extension, if any
|
@@ -404,14 +429,22 @@ module SPARQL; module Algebra
|
|
404
429
|
str << "GROUP BY #{ops.join(' ')}\n"
|
405
430
|
end
|
406
431
|
|
407
|
-
#
|
432
|
+
# HavingClause
|
433
|
+
unless having_ops.empty?
|
434
|
+
str << "HAVING #{having_ops.to_sparql(**options)}"
|
435
|
+
end
|
436
|
+
|
437
|
+
# OrderClause
|
408
438
|
unless order_ops.empty?
|
409
439
|
str << "ORDER BY #{order_ops.to_sparql(**options)}\n"
|
410
440
|
end
|
411
441
|
|
412
|
-
#
|
442
|
+
# LimitOffsetClauses
|
413
443
|
str << "OFFSET #{offset}\n" unless offset.nil?
|
414
444
|
str << "LIMIT #{limit}\n" unless limit.nil?
|
445
|
+
|
446
|
+
# Values Clause
|
447
|
+
str << values_clause.to_sparql(top_level: false, **options) if values_clause
|
415
448
|
str
|
416
449
|
end
|
417
450
|
|
@@ -640,12 +673,8 @@ module SPARQL; module Algebra
|
|
640
673
|
# @return [SPARQL::Algebra::Expression] `self`
|
641
674
|
def rewrite(&block)
|
642
675
|
@operands = @operands.map do |op|
|
643
|
-
|
644
|
-
|
645
|
-
# Not re-written, rewrite
|
646
|
-
new_op = op.respond_to?(:rewrite) ? op.rewrite(&block) : op
|
647
|
-
end
|
648
|
-
new_op
|
676
|
+
new_op = block.call(op)
|
677
|
+
new_op.respond_to?(:rewrite) ? new_op.rewrite(&block) : new_op
|
649
678
|
end
|
650
679
|
self
|
651
680
|
end
|
@@ -671,7 +700,6 @@ module SPARQL; module Algebra
|
|
671
700
|
end
|
672
701
|
|
673
702
|
##
|
674
|
-
#
|
675
703
|
# Returns a partial SPARQL grammar for the operator.
|
676
704
|
#
|
677
705
|
# @return [String]
|
data/lib/sparql/algebra.rb
CHANGED
@@ -19,6 +19,24 @@ module SPARQL
|
|
19
19
|
#
|
20
20
|
# {RDF::Query} and {RDF::Query::Pattern} are used as primitives for `bgp` and `triple` expressions.
|
21
21
|
#
|
22
|
+
# # Background
|
23
|
+
#
|
24
|
+
# The SPARQL Algebra, and the S-Expressions used to represent it, are based on those of [Jena](https://jena.apache.org/documentation/notes/sse.html). Generally, an S-Expression generated by this Gem can be used as an SSE input to Jena, or an SSE output from Jena can also be used as input to this Gem.
|
25
|
+
#
|
26
|
+
# S-Expressions generally follow a standardized nesting resulting from parsing the original SPARQL Grammar. The individual operators map to SPARQL Grammar productions, and in most cases, the SPARQL Grammar can be reproduced by turning the S-Expression back into SPARQL (see {SPARQL::Algebra::Operator#to_sparql}). The order of operations will typically be as follows:
|
27
|
+
#
|
28
|
+
# * {SPARQL::Algebra::Operator::Base}
|
29
|
+
# * {SPARQL::Algebra::Operator::Prefix}
|
30
|
+
# * {SPARQL::Algebra::Operator::Slice}
|
31
|
+
# * {SPARQL::Algebra::Operator::Distinct}
|
32
|
+
# * {SPARQL::Algebra::Operator::Reduced}
|
33
|
+
# * {SPARQL::Algebra::Operator::Project}
|
34
|
+
# * {SPARQL::Algebra::Operator::Order}
|
35
|
+
# * {SPARQL::Algebra::Operator::Filter}
|
36
|
+
# * {SPARQL::Algebra::Operator::Extend}
|
37
|
+
# * {SPARQL::Algebra::Operator::Group}
|
38
|
+
# * {SPARQL::Algebra::Query} (many classes implement Query)
|
39
|
+
#
|
22
40
|
# # Queries
|
23
41
|
#
|
24
42
|
# require 'sparql/algebra'
|
@@ -262,6 +280,7 @@ module SPARQL
|
|
262
280
|
# * {SPARQL::Algebra::Operator::Extend}
|
263
281
|
# * {SPARQL::Algebra::Operator::Filter}
|
264
282
|
# * {SPARQL::Algebra::Operator::Floor}
|
283
|
+
# * {SPARQL::Algebra::Operator::FunctionCall}
|
265
284
|
# * {SPARQL::Algebra::Operator::Graph}
|
266
285
|
# * {SPARQL::Algebra::Operator::GreaterThan}
|
267
286
|
# * {SPARQL::Algebra::Operator::GreaterThanOrEqual}
|
@@ -339,11 +358,9 @@ module SPARQL
|
|
339
358
|
# * {SPARQL::Algebra::Operator::With}
|
340
359
|
# * {SPARQL::Algebra::Operator::Year}
|
341
360
|
#
|
342
|
-
# TODO
|
343
|
-
# ====
|
344
|
-
# * Operator#optimize needs to be completed and tested.
|
345
361
|
#
|
346
362
|
# @see http://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
363
|
+
# @see https://jena.apache.org/documentation/notes/sse.html
|
347
364
|
module Algebra
|
348
365
|
include RDF
|
349
366
|
|
@@ -197,7 +197,7 @@ module SPARQL::Grammar
|
|
197
197
|
# [2] Query ::= Prologue
|
198
198
|
# ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
|
199
199
|
production(:Query) do |input, data, callback|
|
200
|
-
query = data[:query].first
|
200
|
+
query = data[:query].first if data[:query]
|
201
201
|
|
202
202
|
# Add prefix
|
203
203
|
if data[:PrefixDecl]
|
@@ -806,7 +806,7 @@ module SPARQL::Grammar
|
|
806
806
|
|
807
807
|
# [70] FunctionCall ::= iri ArgList
|
808
808
|
production(:FunctionCall) do |input, data, callback|
|
809
|
-
add_prod_data(:Function,
|
809
|
+
add_prod_data(:Function, SPARQL::Algebra::Operator::FunctionCall.new(data[:iri], *data[:ArgList]))
|
810
810
|
end
|
811
811
|
|
812
812
|
# [71] ArgList ::= NIL
|
@@ -1437,7 +1437,7 @@ module SPARQL::Grammar
|
|
1437
1437
|
production(:iriOrFunction) do |input, data, callback|
|
1438
1438
|
if data.has_key?(:ArgList)
|
1439
1439
|
# Function is (func arg1 arg2 ...)
|
1440
|
-
add_prod_data(:Function,
|
1440
|
+
add_prod_data(:Function, SPARQL::Algebra::Operator::FunctionCall.new(data[:iri], *data[:ArgList]))
|
1441
1441
|
else
|
1442
1442
|
input[:iri] = data[:iri]
|
1443
1443
|
end
|