sparql 3.1.6 → 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 +31 -22
- data/VERSION +1 -1
- data/bin/sparql +14 -4
- data/lib/sparql/algebra/aggregate.rb +1 -1
- data/lib/sparql/algebra/evaluatable.rb +4 -4
- data/lib/sparql/algebra/expression.rb +28 -3
- data/lib/sparql/algebra/extensions.rb +109 -45
- data/lib/sparql/algebra/operator/abs.rb +23 -3
- data/lib/sparql/algebra/operator/add.rb +21 -2
- data/lib/sparql/algebra/operator/alt.rb +26 -2
- data/lib/sparql/algebra/operator/and.rb +25 -3
- data/lib/sparql/algebra/operator/asc.rb +20 -1
- data/lib/sparql/algebra/operator/ask.rb +17 -1
- data/lib/sparql/algebra/operator/avg.rb +20 -2
- data/lib/sparql/algebra/operator/base.rb +18 -1
- data/lib/sparql/algebra/operator/bgp.rb +13 -1
- data/lib/sparql/algebra/operator/bnode.rb +34 -11
- data/lib/sparql/algebra/operator/bound.rb +22 -1
- data/lib/sparql/algebra/operator/ceil.rb +26 -3
- data/lib/sparql/algebra/operator/clear.rb +26 -2
- data/lib/sparql/algebra/operator/coalesce.rb +33 -11
- data/lib/sparql/algebra/operator/compare.rb +48 -40
- data/lib/sparql/algebra/operator/concat.rb +26 -2
- data/lib/sparql/algebra/operator/construct.rb +29 -6
- data/lib/sparql/algebra/operator/contains.rb +25 -3
- data/lib/sparql/algebra/operator/copy.rb +19 -2
- data/lib/sparql/algebra/operator/count.rb +53 -7
- data/lib/sparql/algebra/operator/create.rb +20 -2
- data/lib/sparql/algebra/operator/dataset.rb +27 -2
- data/lib/sparql/algebra/operator/datatype.rb +26 -7
- data/lib/sparql/algebra/operator/day.rb +24 -6
- data/lib/sparql/algebra/operator/delete.rb +29 -2
- data/lib/sparql/algebra/operator/delete_data.rb +23 -2
- data/lib/sparql/algebra/operator/delete_where.rb +24 -2
- data/lib/sparql/algebra/operator/desc.rb +20 -1
- data/lib/sparql/algebra/operator/describe.rb +27 -4
- data/lib/sparql/algebra/operator/distinct.rb +20 -3
- data/lib/sparql/algebra/operator/divide.rb +27 -3
- data/lib/sparql/algebra/operator/drop.rb +27 -3
- data/lib/sparql/algebra/operator/encode_for_uri.rb +23 -3
- data/lib/sparql/algebra/operator/equal.rb +13 -3
- data/lib/sparql/algebra/operator/exists.rb +28 -4
- data/lib/sparql/algebra/operator/exprlist.rb +15 -2
- data/lib/sparql/algebra/operator/extend.rb +64 -6
- data/lib/sparql/algebra/operator/filter.rb +27 -5
- data/lib/sparql/algebra/operator/floor.rb +26 -3
- data/lib/sparql/algebra/operator/function_call.rb +64 -0
- data/lib/sparql/algebra/operator/graph.rb +69 -6
- data/lib/sparql/algebra/operator/greater_than.rb +14 -4
- data/lib/sparql/algebra/operator/greater_than_or_equal.rb +14 -4
- data/lib/sparql/algebra/operator/group.rb +105 -8
- data/lib/sparql/algebra/operator/group_concat.rb +44 -8
- data/lib/sparql/algebra/operator/hours.rb +24 -6
- data/lib/sparql/algebra/operator/if.rb +20 -3
- data/lib/sparql/algebra/operator/in.rb +18 -1
- data/lib/sparql/algebra/operator/insert.rb +24 -2
- data/lib/sparql/algebra/operator/insert_data.rb +23 -2
- data/lib/sparql/algebra/operator/iri.rb +22 -5
- data/lib/sparql/algebra/operator/is_blank.rb +21 -4
- data/lib/sparql/algebra/operator/is_iri.rb +21 -4
- data/lib/sparql/algebra/operator/is_literal.rb +21 -4
- data/lib/sparql/algebra/operator/is_numeric.rb +23 -6
- data/lib/sparql/algebra/operator/is_triple.rb +33 -1
- data/lib/sparql/algebra/operator/join.rb +56 -1
- data/lib/sparql/algebra/operator/lang.rb +26 -1
- data/lib/sparql/algebra/operator/lang_matches.rb +23 -2
- data/lib/sparql/algebra/operator/lcase.rb +23 -3
- data/lib/sparql/algebra/operator/left_join.rb +42 -1
- data/lib/sparql/algebra/operator/less_than.rb +14 -4
- data/lib/sparql/algebra/operator/less_than_or_equal.rb +14 -4
- data/lib/sparql/algebra/operator/load.rb +25 -2
- data/lib/sparql/algebra/operator/max.rb +20 -2
- data/lib/sparql/algebra/operator/md5.rb +23 -6
- data/lib/sparql/algebra/operator/min.rb +22 -4
- data/lib/sparql/algebra/operator/minus.rb +65 -7
- data/lib/sparql/algebra/operator/minutes.rb +24 -6
- data/lib/sparql/algebra/operator/modify.rb +41 -5
- data/lib/sparql/algebra/operator/month.rb +24 -6
- data/lib/sparql/algebra/operator/move.rb +20 -2
- data/lib/sparql/algebra/operator/multiply.rb +27 -4
- data/lib/sparql/algebra/operator/negate.rb +24 -4
- data/lib/sparql/algebra/operator/not.rb +25 -4
- data/lib/sparql/algebra/operator/not_equal.rb +16 -1
- data/lib/sparql/algebra/operator/notexists.rb +30 -6
- data/lib/sparql/algebra/operator/notin.rb +20 -3
- data/lib/sparql/algebra/operator/notoneof.rb +21 -2
- data/lib/sparql/algebra/operator/now.rb +25 -6
- data/lib/sparql/algebra/operator/object.rb +33 -1
- data/lib/sparql/algebra/operator/or.rb +26 -3
- data/lib/sparql/algebra/operator/order.rb +71 -2
- data/lib/sparql/algebra/operator/path.rb +29 -2
- data/lib/sparql/algebra/operator/path_opt.rb +21 -2
- data/lib/sparql/algebra/operator/path_plus.rb +21 -2
- data/lib/sparql/algebra/operator/path_star.rb +20 -2
- data/lib/sparql/algebra/operator/plus.rb +43 -4
- data/lib/sparql/algebra/operator/predicate.rb +33 -1
- data/lib/sparql/algebra/operator/prefix.rb +24 -3
- data/lib/sparql/algebra/operator/project.rb +69 -5
- data/lib/sparql/algebra/operator/rand.rb +31 -3
- data/lib/sparql/algebra/operator/reduced.rb +20 -3
- data/lib/sparql/algebra/operator/regex.rb +27 -19
- data/lib/sparql/algebra/operator/replace.rb +27 -7
- data/lib/sparql/algebra/operator/reverse.rb +31 -2
- data/lib/sparql/algebra/operator/round.rb +26 -3
- data/lib/sparql/algebra/operator/same_term.rb +25 -7
- data/lib/sparql/algebra/operator/sample.rb +33 -9
- data/lib/sparql/algebra/operator/seconds.rb +24 -6
- data/lib/sparql/algebra/operator/seq.rb +20 -2
- data/lib/sparql/algebra/operator/sequence.rb +4 -11
- data/lib/sparql/algebra/operator/sha1.rb +19 -2
- data/lib/sparql/algebra/operator/sha256.rb +19 -2
- data/lib/sparql/algebra/operator/sha384.rb +19 -2
- data/lib/sparql/algebra/operator/sha512.rb +19 -2
- data/lib/sparql/algebra/operator/slice.rb +27 -5
- data/lib/sparql/algebra/operator/str.rb +22 -2
- data/lib/sparql/algebra/operator/strafter.rb +26 -3
- data/lib/sparql/algebra/operator/strbefore.rb +26 -3
- data/lib/sparql/algebra/operator/strdt.rb +23 -2
- data/lib/sparql/algebra/operator/strends.rb +26 -4
- data/lib/sparql/algebra/operator/strlang.rb +25 -7
- data/lib/sparql/algebra/operator/strlen.rb +24 -3
- data/lib/sparql/algebra/operator/strstarts.rb +26 -3
- data/lib/sparql/algebra/operator/struuid.rb +30 -10
- data/lib/sparql/algebra/operator/subject.rb +33 -1
- data/lib/sparql/algebra/operator/substr.rb +24 -3
- data/lib/sparql/algebra/operator/subtract.rb +29 -3
- data/lib/sparql/algebra/operator/sum.rb +25 -7
- data/lib/sparql/algebra/operator/table.rb +76 -4
- data/lib/sparql/algebra/operator/timezone.rb +24 -6
- data/lib/sparql/algebra/operator/tz.rb +23 -6
- data/lib/sparql/algebra/operator/ucase.rb +24 -3
- data/lib/sparql/algebra/operator/union.rb +29 -6
- data/lib/sparql/algebra/operator/update.rb +46 -4
- data/lib/sparql/algebra/operator/using.rb +49 -2
- data/lib/sparql/algebra/operator/uuid.rb +28 -9
- data/lib/sparql/algebra/operator/with.rb +38 -4
- data/lib/sparql/algebra/operator/year.rb +24 -6
- data/lib/sparql/algebra/operator.rb +135 -14
- data/lib/sparql/algebra/sxp_extensions.rb +3 -3
- data/lib/sparql/algebra.rb +20 -3
- data/lib/sparql/grammar/meta.rb +1103 -907
- data/lib/sparql/grammar/parser11.rb +63 -56
- metadata +43 -29
- data/lib/sparql/algebra/operator/triple.rb +0 -27
@@ -3,11 +3,44 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL GraphPattern `prefix` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [29] Update ::= Prologue ( Update1 ( ';' Update )? )?
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example.org/>
|
10
|
+
# PREFIX foaf: <http://xmlns.com/foaf/0.1/>
|
11
|
+
# DELETE { ?a foaf:knows ?b }
|
12
|
+
# INSERT { ?b foaf:knows ?a }
|
13
|
+
# WHERE { ?a foaf:knows ?b }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example.org/>)
|
17
|
+
# (foaf: <http://xmlns.com/foaf/0.1/>))
|
18
|
+
# (update
|
19
|
+
# (modify
|
20
|
+
# (bgp (triple ?a foaf:knows ?b))
|
21
|
+
# (delete ((triple ?a foaf:knows ?b)))
|
22
|
+
# (insert ((triple ?b foaf:knows ?a)))) ))
|
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))))
|
8
41
|
# (modify
|
9
|
-
#
|
10
|
-
#
|
42
|
+
# (bgp (triple ?a foaf:knows ?b))
|
43
|
+
# (insert ((triple ?b foaf:knows ?a))))))
|
11
44
|
#
|
12
45
|
# @see https://www.w3.org/TR/sparql11-update/#graphUpdate
|
13
46
|
class Update < Operator
|
@@ -39,6 +72,15 @@ module SPARQL; module Algebra
|
|
39
72
|
end
|
40
73
|
queryable
|
41
74
|
end
|
75
|
+
|
76
|
+
##
|
77
|
+
#
|
78
|
+
# Returns a partial SPARQL grammar for this operator.
|
79
|
+
#
|
80
|
+
# @return [String]
|
81
|
+
def to_sparql(**options)
|
82
|
+
str = operands.map { |e| e.to_sparql(**options) }.join(";\n")
|
83
|
+
end
|
42
84
|
end # Update
|
43
85
|
end # Operator
|
44
86
|
end; end # SPARQL::Algebra
|
@@ -6,8 +6,42 @@ module SPARQL; module Algebra
|
|
6
6
|
#
|
7
7
|
# The USING and USING NAMED clauses affect the RDF Dataset used while evaluating the WHERE clause. This describes a dataset in the same way as FROM and FROM NAMED clauses describe RDF Datasets in the SPARQL 1.1 Query Language
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# [44] UsingClause ::= 'USING' ( iri | 'NAMED' iri )
|
10
|
+
#
|
11
|
+
# @example SPARQL Grammar
|
12
|
+
# PREFIX : <http://example.org/>
|
13
|
+
# PREFIX foaf: <http://xmlns.com/foaf/0.1/>
|
14
|
+
#
|
15
|
+
# DELETE { ?s ?p ?o }
|
16
|
+
# USING <http://example.org/g2>
|
17
|
+
# WHERE {
|
18
|
+
# :a foaf:knows ?s .
|
19
|
+
# ?s ?p ?o
|
20
|
+
# }
|
21
|
+
#
|
22
|
+
# @example SSE
|
23
|
+
# (prefix
|
24
|
+
# ((: <http://example.org/>) (foaf: <http://xmlns.com/foaf/0.1/>))
|
25
|
+
# (update
|
26
|
+
# (modify
|
27
|
+
# (using (:g2)
|
28
|
+
# (bgp (triple :a foaf:knows ?s) (triple ?s ?p ?o)))
|
29
|
+
# (delete ((triple ?s ?p ?o)))) ))
|
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"))))))
|
11
45
|
#
|
12
46
|
# @see https://www.w3.org/TR/sparql11-update/#add
|
13
47
|
class Using < Operator
|
@@ -35,6 +69,19 @@ module SPARQL; module Algebra
|
|
35
69
|
debug(options) {"Using"}
|
36
70
|
Dataset.new(*operands).execute(queryable, depth: options[:depth].to_i + 1, **options, &block)
|
37
71
|
end
|
72
|
+
|
73
|
+
##
|
74
|
+
#
|
75
|
+
# Returns a partial SPARQL grammar for this operator.
|
76
|
+
#
|
77
|
+
# @return [String]
|
78
|
+
def to_sparql(**options)
|
79
|
+
str = "\n" + operands.first.map do |op|
|
80
|
+
"USING #{op.to_sparql(**options)}\n"
|
81
|
+
end.join("")
|
82
|
+
content = operands.last.to_sparql(top_level: false, **options)
|
83
|
+
str << Operator.to_sparql(content, project: nil, **options)
|
84
|
+
end
|
38
85
|
end # Using
|
39
86
|
end # Operator
|
40
87
|
end; end # SPARQL::Algebra
|
@@ -5,14 +5,24 @@ module SPARQL; module Algebra
|
|
5
5
|
##
|
6
6
|
# The SPARQL `uuid` function.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
8
|
+
# [121] BuiltInCall ::= ... | 'UUID' NIL
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX : <http://example.org/>
|
12
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
13
|
+
# ASK {
|
14
|
+
# BIND(UUID() AS ?u1)
|
15
|
+
# BIND(UUID() AS ?u2)
|
16
|
+
# FILTER(?u1 != ?u2)
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example SSE
|
20
|
+
# (prefix
|
21
|
+
# ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
22
|
+
# (ask
|
23
|
+
# (filter (!= ?u1 ?u2)
|
24
|
+
# (extend ((?u1 (uuid)) (?u2 (uuid)))
|
25
|
+
# (bgp)))))
|
16
26
|
#
|
17
27
|
# @see https://www.w3.org/TR/sparql11-query/#func-uuid
|
18
28
|
class UUID < Operator::Nullary
|
@@ -24,9 +34,18 @@ module SPARQL; module Algebra
|
|
24
34
|
# Return a fresh IRI from the UUID URN scheme. Each call of UUID() returns a different UUID. It must not be the "nil" UUID (all zeroes). The variant and version of the UUID is implementation dependent.
|
25
35
|
#
|
26
36
|
# @return [RDF::URI]
|
27
|
-
def apply
|
37
|
+
def apply(**options)
|
28
38
|
RDF::URI("urn:uuid:#{SecureRandom.uuid}")
|
29
39
|
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# Returns a partial SPARQL grammar for this operator.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def to_sparql(**options)
|
47
|
+
"UUID(" + operands.to_sparql(delimiter: ', ', **options) + ")"
|
48
|
+
end
|
30
49
|
end # UUID
|
31
50
|
end # Operator
|
32
51
|
end; end # SPARQL::Algebra
|
@@ -6,10 +6,21 @@ module SPARQL; module Algebra
|
|
6
6
|
#
|
7
7
|
# The WITH clause provides a convenience for when an operation primarily refers to a single graph.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
9
|
+
# [41] Modify ::= ( 'WITH' iri )? ( DeleteClause InsertClause? | InsertClause ) UsingClause* 'WHERE' GroupGraphPattern
|
10
|
+
#
|
11
|
+
# @example SPARQL Grammar
|
12
|
+
# PREFIX : <http://example/>
|
13
|
+
# WITH :g
|
14
|
+
# DELETE { <base:s> ?p ?o . }
|
15
|
+
# WHERE { ?s ?p ?o }
|
16
|
+
#
|
17
|
+
# @example SSE
|
18
|
+
# (prefix ((: <http://example/>))
|
19
|
+
# (update
|
20
|
+
# (modify
|
21
|
+
# (with :g
|
22
|
+
# (bgp (triple ?s ?p ?o))
|
23
|
+
# (delete ((triple <base:s> ?p ?o)))))))
|
13
24
|
#
|
14
25
|
# @see https://www.w3.org/TR/sparql11-update/#deleteInsert
|
15
26
|
class With < Operator
|
@@ -67,6 +78,29 @@ module SPARQL; module Algebra
|
|
67
78
|
end
|
68
79
|
end
|
69
80
|
end
|
81
|
+
|
82
|
+
##
|
83
|
+
#
|
84
|
+
# Returns a partial SPARQL grammar for this operator.
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
def to_sparql(**options)
|
88
|
+
with, where, *ops = operands
|
89
|
+
str = "WITH #{with.to_sparql(**options)}\n"
|
90
|
+
|
91
|
+
# The content of the WHERE clause, may be USING
|
92
|
+
content = where.to_sparql(top_level: false, **options)
|
93
|
+
|
94
|
+
# DELETE | INSERT | DELETE INSERT
|
95
|
+
str << ops.to_sparql(top_level: false, delimiter: "\n", **options) + "\n"
|
96
|
+
|
97
|
+
# Append the WHERE or USING clause
|
98
|
+
str << if where.is_a?(Using)
|
99
|
+
content
|
100
|
+
else
|
101
|
+
Operator.to_sparql(content, project: nil, **options)
|
102
|
+
end
|
103
|
+
end
|
70
104
|
end # With
|
71
105
|
end # Operator
|
72
106
|
end; end # SPARQL::Algebra
|
@@ -5,11 +5,20 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# Returns the year part of `arg` as an integer.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
8
|
+
# [121] BuiltInCall ::= ... | 'YEAR' '(' Expression ')'
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX : <http://example.org/>
|
12
|
+
# SELECT ?s (YEAR(?date) AS ?x) WHERE {
|
13
|
+
# ?s :date ?date
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# @example SSE
|
17
|
+
# (prefix
|
18
|
+
# ((: <http://example.org/>))
|
19
|
+
# (project (?s ?x)
|
20
|
+
# (extend ((?x (year ?date)))
|
21
|
+
# (bgp (triple ?s :date ?date)))))
|
13
22
|
#
|
14
23
|
# @see https://www.w3.org/TR/sparql11-query/#func-year
|
15
24
|
class Year < Operator::Unary
|
@@ -24,10 +33,19 @@ module SPARQL; module Algebra
|
|
24
33
|
# the operand
|
25
34
|
# @return [RDF::Literal]
|
26
35
|
# @raise [TypeError] if the operand is not a simple literal
|
27
|
-
def apply(operand)
|
36
|
+
def apply(operand, **options)
|
28
37
|
raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
|
29
38
|
RDF::Literal(operand.object.year)
|
30
39
|
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# Returns a partial SPARQL grammar for this operator.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def to_sparql(**options)
|
47
|
+
"YEAR(#{operands.last.to_sparql(**options)})"
|
48
|
+
end
|
31
49
|
end # Year
|
32
50
|
end # Operator
|
33
51
|
end; end # SPARQL::Algebra
|
@@ -49,6 +49,7 @@ module SPARQL; module Algebra
|
|
49
49
|
autoload :Sum, 'sparql/algebra/operator/sum'
|
50
50
|
autoload :SHA1, 'sparql/algebra/operator/sha1'
|
51
51
|
autoload :SHA256, 'sparql/algebra/operator/sha256'
|
52
|
+
autoload :SHA384, 'sparql/algebra/operator/sha384'
|
52
53
|
autoload :SHA512, 'sparql/algebra/operator/sha512'
|
53
54
|
autoload :Str, 'sparql/algebra/operator/str'
|
54
55
|
autoload :Timezone, 'sparql/algebra/operator/timezone'
|
@@ -105,6 +106,7 @@ module SPARQL; module Algebra
|
|
105
106
|
autoload :Coalesce, 'sparql/algebra/operator/coalesce'
|
106
107
|
autoload :Desc, 'sparql/algebra/operator/desc'
|
107
108
|
autoload :Exprlist, 'sparql/algebra/operator/exprlist'
|
109
|
+
autoload :FunctionCall, 'sparql/algebra/operator/function_call'
|
108
110
|
autoload :GroupConcat, 'sparql/algebra/operator/group_concat'
|
109
111
|
autoload :In, 'sparql/algebra/operator/in'
|
110
112
|
autoload :NotIn, 'sparql/algebra/operator/notin'
|
@@ -171,7 +173,6 @@ module SPARQL; module Algebra
|
|
171
173
|
when :> then GreaterThan
|
172
174
|
when :>= then GreaterThanOrEqual
|
173
175
|
when :abs then Abs
|
174
|
-
when :add then Add
|
175
176
|
when :alt then Alt
|
176
177
|
when :and, :'&&' then And
|
177
178
|
when :avg then Avg
|
@@ -204,7 +205,6 @@ module SPARQL; module Algebra
|
|
204
205
|
when :md5 then MD5
|
205
206
|
when :max then Max
|
206
207
|
when :min then Min
|
207
|
-
when :minus then Minus
|
208
208
|
when :minutes then Minutes
|
209
209
|
when :month then Month
|
210
210
|
when :multiply then Multiply
|
@@ -231,6 +231,7 @@ module SPARQL; module Algebra
|
|
231
231
|
when :sequence then Sequence
|
232
232
|
when :sha1 then SHA1
|
233
233
|
when :sha256 then SHA256
|
234
|
+
when :sha384 then SHA384
|
234
235
|
when :sha512 then SHA512
|
235
236
|
when :str then Str
|
236
237
|
when :strafter then StrAfter
|
@@ -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
|
@@ -278,7 +280,6 @@ module SPARQL; module Algebra
|
|
278
280
|
when :reduced then Reduced
|
279
281
|
when :slice then Slice
|
280
282
|
when :table then Table
|
281
|
-
when :triple then RDF::Query::Pattern
|
282
283
|
when :union then Union
|
283
284
|
|
284
285
|
# Update forms
|
@@ -301,7 +302,7 @@ module SPARQL; module Algebra
|
|
301
302
|
|
302
303
|
# RDF-star
|
303
304
|
when :istriple then IsTriple
|
304
|
-
when :triple then
|
305
|
+
when :triple then RDF::Query::Pattern
|
305
306
|
when :subject then Subject
|
306
307
|
when :predicate then Predicate
|
307
308
|
when :object then Object
|
@@ -314,8 +315,8 @@ module SPARQL; module Algebra
|
|
314
315
|
# @param [Array<RDF::Term>] operands
|
315
316
|
# @return [RDF::Term]
|
316
317
|
# @see Operator#evaluate
|
317
|
-
def self.evaluate(*operands)
|
318
|
-
self.new(*operands).evaluate(RDF::Query::Solution.new)
|
318
|
+
def self.evaluate(*operands, **options)
|
319
|
+
self.new(*operands, **options).evaluate(RDF::Query::Solution.new, **options)
|
319
320
|
end
|
320
321
|
|
321
322
|
##
|
@@ -333,6 +334,120 @@ module SPARQL; module Algebra
|
|
333
334
|
self.const_get(:ARITY)
|
334
335
|
end
|
335
336
|
|
337
|
+
##
|
338
|
+
# Generate a top-level Grammar, using collected options
|
339
|
+
#
|
340
|
+
# @param [String] content
|
341
|
+
# @param [Operator] datasets ([])
|
342
|
+
# @param [Operator] distinct (false)
|
343
|
+
# @param [Hash{Symbol => Operator}] extensions
|
344
|
+
# Variable bindings
|
345
|
+
# @param [Array<Operator>] filter_ops ([])
|
346
|
+
# Filter Operations
|
347
|
+
# @param [Integer] limit (nil)
|
348
|
+
# @param [Array<Operator>] group_ops ([])
|
349
|
+
# @param [Array<Operator>] having_ops ([])
|
350
|
+
# @param [Integer] offset (nil)
|
351
|
+
# @param [Array<Operator>] order_ops ([])
|
352
|
+
# Order Operations
|
353
|
+
# @param [Array<Symbol,Operator>] project (%i(*))
|
354
|
+
# Terms to project
|
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
|
360
|
+
# @param [Hash{Symbol => Object}] options
|
361
|
+
# @return [String]
|
362
|
+
def self.to_sparql(content,
|
363
|
+
datasets: [],
|
364
|
+
distinct: false,
|
365
|
+
extensions: {},
|
366
|
+
filter_ops: [],
|
367
|
+
group_ops: [],
|
368
|
+
having_ops: [],
|
369
|
+
limit: nil,
|
370
|
+
offset: nil,
|
371
|
+
order_ops: [],
|
372
|
+
project: %i(*),
|
373
|
+
reduced: false,
|
374
|
+
values_clause: nil,
|
375
|
+
where_clause: true,
|
376
|
+
**options)
|
377
|
+
str = ""
|
378
|
+
|
379
|
+
# Projections
|
380
|
+
if project
|
381
|
+
str << "SELECT "
|
382
|
+
str << "DISTINCT " if distinct
|
383
|
+
str << "REDUCED " if reduced
|
384
|
+
|
385
|
+
str << project.map do |p|
|
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)
|
390
|
+
# Replace projected variables with their extension, if any
|
391
|
+
'(' + v + ' AS ' + pp + ')'
|
392
|
+
else
|
393
|
+
p.to_sparql(**options)
|
394
|
+
end
|
395
|
+
end.join(" ") + "\n"
|
396
|
+
end
|
397
|
+
|
398
|
+
# DatasetClause
|
399
|
+
datasets.each do |ds|
|
400
|
+
str << "FROM #{ds.to_sparql(**options)}\n"
|
401
|
+
end
|
402
|
+
|
403
|
+
# Bind
|
404
|
+
extensions.each do |as, expression|
|
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) << ") ."
|
408
|
+
end
|
409
|
+
|
410
|
+
# Filter
|
411
|
+
filter_ops.each do |f|
|
412
|
+
content << "\nFILTER (#{f.to_sparql(**options)}) ."
|
413
|
+
end
|
414
|
+
|
415
|
+
# WhereClause / GroupGraphPattern
|
416
|
+
str << (where_clause ? "WHERE {\n#{content}\n}\n" : "{\n#{content}\n}\n")
|
417
|
+
|
418
|
+
##
|
419
|
+
# SolutionModifier
|
420
|
+
#
|
421
|
+
# GroupClause
|
422
|
+
unless group_ops.empty?
|
423
|
+
ops = group_ops.map do |o|
|
424
|
+
# Replace projected variables with their extension, if any
|
425
|
+
o.is_a?(Array) ?
|
426
|
+
"(" + [o.last, :AS, o.first].to_sparql(**options) + ")" :
|
427
|
+
o.to_sparql(**options)
|
428
|
+
end
|
429
|
+
str << "GROUP BY #{ops.join(' ')}\n"
|
430
|
+
end
|
431
|
+
|
432
|
+
# HavingClause
|
433
|
+
unless having_ops.empty?
|
434
|
+
str << "HAVING #{having_ops.to_sparql(**options)}"
|
435
|
+
end
|
436
|
+
|
437
|
+
# OrderClause
|
438
|
+
unless order_ops.empty?
|
439
|
+
str << "ORDER BY #{order_ops.to_sparql(**options)}\n"
|
440
|
+
end
|
441
|
+
|
442
|
+
# LimitOffsetClauses
|
443
|
+
str << "OFFSET #{offset}\n" unless offset.nil?
|
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
|
448
|
+
str
|
449
|
+
end
|
450
|
+
|
336
451
|
ARITY = -1 # variable arity
|
337
452
|
|
338
453
|
##
|
@@ -558,12 +673,8 @@ module SPARQL; module Algebra
|
|
558
673
|
# @return [SPARQL::Algebra::Expression] `self`
|
559
674
|
def rewrite(&block)
|
560
675
|
@operands = @operands.map do |op|
|
561
|
-
|
562
|
-
|
563
|
-
# Not re-written, rewrite
|
564
|
-
new_op = op.respond_to?(:rewrite) ? op.rewrite(&block) : op
|
565
|
-
end
|
566
|
-
new_op
|
676
|
+
new_op = block.call(op)
|
677
|
+
new_op.respond_to?(:rewrite) ? new_op.rewrite(&block) : new_op
|
567
678
|
end
|
568
679
|
self
|
569
680
|
end
|
@@ -581,9 +692,19 @@ module SPARQL; module Algebra
|
|
581
692
|
##
|
582
693
|
# Returns an S-Expression (SXP) representation of this operator
|
583
694
|
#
|
695
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes (nil)
|
696
|
+
# @param [RDF::URI] base_uri (nil)
|
697
|
+
# @return [String]
|
698
|
+
def to_sxp(prefixes: nil, base_uri: nil)
|
699
|
+
to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
|
700
|
+
end
|
701
|
+
|
702
|
+
##
|
703
|
+
# Returns a partial SPARQL grammar for the operator.
|
704
|
+
#
|
584
705
|
# @return [String]
|
585
|
-
def
|
586
|
-
|
706
|
+
def to_sparql(**options)
|
707
|
+
raise NotImplementedError, "#{self.class}#to_sparql(#{operands.map(&:class).join(', ')})"
|
587
708
|
end
|
588
709
|
|
589
710
|
##
|
@@ -5,7 +5,7 @@ class NilClass
|
|
5
5
|
# Returns the SXP representation of this object.
|
6
6
|
#
|
7
7
|
# @return [String]
|
8
|
-
def to_sxp
|
8
|
+
def to_sxp(**options)
|
9
9
|
RDF.nil.to_s
|
10
10
|
end
|
11
11
|
end
|
@@ -17,7 +17,7 @@ class FalseClass
|
|
17
17
|
# Returns the SXP representation of this object.
|
18
18
|
#
|
19
19
|
# @return [String]
|
20
|
-
def to_sxp
|
20
|
+
def to_sxp(**options)
|
21
21
|
'false'
|
22
22
|
end
|
23
23
|
end
|
@@ -29,7 +29,7 @@ class TrueClass
|
|
29
29
|
# Returns the SXP representation of this object.
|
30
30
|
#
|
31
31
|
# @return [String]
|
32
|
-
def to_sxp
|
32
|
+
def to_sxp(**options)
|
33
33
|
'true'
|
34
34
|
end
|
35
35
|
end
|
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
|
|