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
@@ -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
|