sparql 3.1.5 → 3.2.0
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 +35 -28
- 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 +4 -1
- data/lib/sparql/algebra/extensions.rb +96 -29
- 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 +18 -2
- data/lib/sparql/algebra/operator/base.rb +18 -1
- data/lib/sparql/algebra/operator/bgp.rb +5 -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 +16 -2
- data/lib/sparql/algebra/operator/coalesce.rb +33 -11
- data/lib/sparql/algebra/operator/compare.rb +48 -33
- data/lib/sparql/algebra/operator/concat.rb +26 -2
- data/lib/sparql/algebra/operator/construct.rb +31 -7
- 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 +18 -2
- data/lib/sparql/algebra/operator/create.rb +19 -2
- data/lib/sparql/algebra/operator/dataset.rb +17 -0
- 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 +27 -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 +18 -1
- data/lib/sparql/algebra/operator/divide.rb +27 -3
- data/lib/sparql/algebra/operator/drop.rb +17 -2
- data/lib/sparql/algebra/operator/encode_for_uri.rb +25 -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 +12 -1
- data/lib/sparql/algebra/operator/extend.rb +33 -18
- data/lib/sparql/algebra/operator/filter.rb +27 -5
- data/lib/sparql/algebra/operator/floor.rb +26 -3
- data/lib/sparql/algebra/operator/graph.rb +13 -0
- 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 +34 -8
- data/lib/sparql/algebra/operator/group_concat.rb +20 -8
- data/lib/sparql/algebra/operator/hours.rb +24 -6
- data/lib/sparql/algebra/operator/if.rb +21 -4
- data/lib/sparql/algebra/operator/in.rb +18 -1
- data/lib/sparql/algebra/operator/insert.rb +22 -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 +20 -2
- data/lib/sparql/algebra/operator/is_iri.rb +20 -2
- data/lib/sparql/algebra/operator/is_literal.rb +20 -2
- data/lib/sparql/algebra/operator/is_numeric.rb +22 -4
- data/lib/sparql/algebra/operator/is_triple.rb +62 -0
- data/lib/sparql/algebra/operator/join.rb +22 -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 +24 -3
- data/lib/sparql/algebra/operator/left_join.rb +29 -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 +18 -2
- data/lib/sparql/algebra/operator/md5.rb +23 -6
- data/lib/sparql/algebra/operator/min.rb +19 -3
- data/lib/sparql/algebra/operator/minus.rb +25 -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 +12 -2
- data/lib/sparql/algebra/operator/now.rb +25 -6
- data/lib/sparql/algebra/operator/object.rb +59 -0
- data/lib/sparql/algebra/operator/or.rb +26 -3
- data/lib/sparql/algebra/operator/order.rb +27 -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 +59 -0
- data/lib/sparql/algebra/operator/prefix.rb +24 -3
- data/lib/sparql/algebra/operator/project.rb +51 -5
- data/lib/sparql/algebra/operator/rand.rb +31 -3
- data/lib/sparql/algebra/operator/reduced.rb +18 -1
- 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 +20 -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 +31 -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 +0 -10
- 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 +26 -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 +61 -0
- 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 +18 -2
- data/lib/sparql/algebra/operator/table.rb +42 -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 +25 -4
- data/lib/sparql/algebra/operator/using.rb +32 -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 +112 -7
- data/lib/sparql/algebra/sxp_extensions.rb +3 -3
- data/lib/sparql/grammar/meta.rb +5390 -2410
- data/lib/sparql/grammar/parser11.rb +119 -53
- data/lib/sparql/grammar/terminals11.rb +2 -0
- data/lib/sparql/grammar.rb +0 -25
- metadata +40 -34
@@ -5,7 +5,13 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# Applications can use the ASK form to test whether or not a query pattern has a solution. No information is returned about the possible query solutions, just whether or not a solution exists.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# [12] AskQuery ::= 'ASK' DatasetClause* WhereClause ValuesClause
|
9
|
+
#
|
10
|
+
# @example SPARQL Query
|
11
|
+
# PREFIX : <http://example/>
|
12
|
+
# ASK { :x :p ?x }
|
13
|
+
#
|
14
|
+
# @example SSE
|
9
15
|
# (prefix ((: <http://example/>))
|
10
16
|
# (ask
|
11
17
|
# (bgp (triple :x :p ?x))))
|
@@ -41,6 +47,16 @@ module SPARQL; module Algebra
|
|
41
47
|
def query_yields_boolean?
|
42
48
|
true
|
43
49
|
end
|
50
|
+
|
51
|
+
##
|
52
|
+
#
|
53
|
+
# Returns a partial SPARQL grammar for this term.
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
def to_sparql(**options)
|
57
|
+
"ASK\n" +
|
58
|
+
operands.first.to_sparql(top_level: true, project: nil, **options)
|
59
|
+
end
|
44
60
|
end # Ask
|
45
61
|
end # Operator
|
46
62
|
end; end # SPARQL::Algebra
|
@@ -3,7 +3,14 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL `avg` set function.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# [127] Aggregate::= ... | 'AVG' '(' 'DISTINCT'? Expression ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Query
|
9
|
+
# PREFIX : <http://www.example.org/>
|
10
|
+
# SELECT (AVG(?o) AS ?avg)
|
11
|
+
# WHERE { ?s :dec ?o }
|
12
|
+
#
|
13
|
+
# @example SSE
|
7
14
|
# (prefix ((: <http://www.example.org/>))
|
8
15
|
# (project (?avg)
|
9
16
|
# (extend ((?avg ??.0))
|
@@ -29,7 +36,7 @@ module SPARQL; module Algebra
|
|
29
36
|
# @param [Enumerable<Array<RDF::Term>>] enum
|
30
37
|
# enum of evaluated operand
|
31
38
|
# @return [RDF::Literal::Numeric] The numeric average of the terms
|
32
|
-
def apply(enum)
|
39
|
+
def apply(enum, **options)
|
33
40
|
# FIXME: we don't actually do anything with distinct
|
34
41
|
operands.shift if distinct = (operands.first == :distinct)
|
35
42
|
if enum.empty?
|
@@ -40,6 +47,15 @@ module SPARQL; module Algebra
|
|
40
47
|
raise TypeError, "Averaging non-numeric types: #{enum.flatten}"
|
41
48
|
end
|
42
49
|
end
|
50
|
+
|
51
|
+
##
|
52
|
+
#
|
53
|
+
# Returns a partial SPARQL grammar for this operator.
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
def to_sparql(**options)
|
57
|
+
"AVG(#{operands.to_sparql(**options)})"
|
58
|
+
end
|
43
59
|
end # Avg
|
44
60
|
end # Operator
|
45
61
|
end; end # SPARQL::Algebra
|
@@ -3,7 +3,13 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL GraphPattern `base` operator.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# [5] BaseDecl ::= 'BASE' IRIREF
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# BASE <http://example.org/>
|
10
|
+
# SELECT * { <a> <b> 123.0 }
|
11
|
+
#
|
12
|
+
# @example SSE
|
7
13
|
# (base <http://example.org/>
|
8
14
|
# (bgp (triple <a> <b> 123.0)))
|
9
15
|
#
|
@@ -56,6 +62,17 @@ module SPARQL; module Algebra
|
|
56
62
|
def query_yields_statements?
|
57
63
|
operands.last.query_yields_statements?
|
58
64
|
end
|
65
|
+
|
66
|
+
##
|
67
|
+
#
|
68
|
+
# Returns a partial SPARQL grammar for this term.
|
69
|
+
#
|
70
|
+
# @return [String]
|
71
|
+
def to_sparql(**options)
|
72
|
+
str = "BASE #{operands.first.to_sparql}\n"
|
73
|
+
|
74
|
+
str << operands.last.to_sparql(base_uri: operands.first, **options)
|
75
|
+
end
|
59
76
|
end # Base
|
60
77
|
end # Operator
|
61
78
|
end; end # SPARQL::Algebra
|
@@ -5,7 +5,11 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# Query with `graph_name` set to false.
|
7
7
|
#
|
8
|
-
# @example
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example/>
|
10
|
+
# SELECT * { :s :p :o }
|
11
|
+
#
|
12
|
+
# @example SSE
|
9
13
|
# (prefix ((: <http://example/>))
|
10
14
|
# (bgp (triple ?s ?p ?o)))
|
11
15
|
#
|
@@ -5,16 +5,30 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# The BNODE function constructs a blank node that is distinct from all blank nodes in the dataset being queried and distinct from all blank nodes created by calls to this constructor for other query solutions. If the no argument form is used, every call results in a distinct blank node. If the form with a simple literal is used, every call results in distinct blank nodes for different simple literals, and the same blank node for calls with the same simple literal within expressions for one solution mapping.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
8
|
+
# [121] BuiltInCall ::= ... | 'BNODE' ( '(' Expression ')' | NIL )
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX : <http://example.org/>
|
12
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
13
|
+
# SELECT ?s1 ?s2 (BNODE(?s1) AS ?b1) (BNODE(?s2) AS ?b2)
|
14
|
+
# WHERE {
|
15
|
+
# ?a :str ?s1 .
|
16
|
+
# ?b :str ?s2 .
|
17
|
+
# FILTER (?a = :s1 || ?a = :s3)
|
18
|
+
# FILTER (?b = :s1 || ?b = :s3)
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# @example SSE
|
22
|
+
# (prefix
|
23
|
+
# ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
24
|
+
# (project (?s1 ?s2 ?b1 ?b2)
|
25
|
+
# (extend
|
26
|
+
# ((?b1 (bnode ?s1)) (?b2 (bnode ?s2)))
|
27
|
+
# (filter
|
28
|
+
# (exprlist
|
29
|
+
# (|| (= ?a :s1) (= ?a :s3))
|
30
|
+
# (|| (= ?b :s1) (= ?b :s3)))
|
31
|
+
# (bgp (triple ?a :str ?s1) (triple ?b :str ?s2))) )) )
|
18
32
|
#
|
19
33
|
# @see https://www.w3.org/TR/sparql11-query/#func-bnode
|
20
34
|
class BNode < Operator::Unary
|
@@ -57,7 +71,7 @@ module SPARQL; module Algebra
|
|
57
71
|
# a query solution containing zero or more variable bindings
|
58
72
|
# @return [RDF::Node]
|
59
73
|
# @raise [TypeError] if the operand is not a simple literal or nil
|
60
|
-
def apply(literal, bindings)
|
74
|
+
def apply(literal, bindings, **options)
|
61
75
|
@@bnode_base ||= "b0"
|
62
76
|
@@bindings ||= bindings
|
63
77
|
@@bnodes ||= {}
|
@@ -86,6 +100,15 @@ module SPARQL; module Algebra
|
|
86
100
|
def to_sxp_bin
|
87
101
|
[NAME] + operands.reject {|o| o == false}
|
88
102
|
end
|
103
|
+
|
104
|
+
##
|
105
|
+
#
|
106
|
+
# Returns a partial SPARQL grammar for this operator.
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
def to_sparql(**options)
|
110
|
+
"BNODE(#{operands.last.to_sparql(**options)})"
|
111
|
+
end
|
89
112
|
end # BNode
|
90
113
|
end # Operator
|
91
114
|
end; end # SPARQL::Algebra
|
@@ -3,7 +3,19 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL `bound` operator.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# [121] BuiltInCall ::= ... | 'BOUND' '(' Var ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example.org/ns#>
|
10
|
+
# SELECT ?a ?c
|
11
|
+
# WHERE
|
12
|
+
# { ?a :b ?c .
|
13
|
+
# OPTIONAL
|
14
|
+
# { ?c :d ?e } .
|
15
|
+
# FILTER (! bound(?e))
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# @example SSE
|
7
19
|
# (prefix ((: <http://example.org/ns#>))
|
8
20
|
# (project (?a ?c)
|
9
21
|
# (filter (! (bound ?e))
|
@@ -46,6 +58,15 @@ module SPARQL; module Algebra
|
|
46
58
|
else raise TypeError, "expected an RDF::Query::Variable, but got #{var.inspect}"
|
47
59
|
end
|
48
60
|
end
|
61
|
+
|
62
|
+
##
|
63
|
+
#
|
64
|
+
# Returns a partial SPARQL grammar for this operator.
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
def to_sparql(**options)
|
68
|
+
"bound(" + operands.first.to_sparql(**options) + ")"
|
69
|
+
end
|
49
70
|
end # Bound
|
50
71
|
end # Operator
|
51
72
|
end; end # SPARQL::Algebra
|
@@ -3,8 +3,22 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL logical `ceil` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [121] BuiltInCall ::= ... 'CEIL' '(' Expression ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example.org/>
|
10
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
11
|
+
# SELECT ?s ?num (CEIL(?num) AS ?ceil) WHERE {
|
12
|
+
# ?s :num ?num
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix
|
17
|
+
# ((: <http://example.org/>)
|
18
|
+
# (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
19
|
+
# (project (?s ?num ?ceil)
|
20
|
+
# (extend ((?ceil (ceil ?num)))
|
21
|
+
# (bgp (triple ?s :num ?num)))))
|
8
22
|
#
|
9
23
|
# @see https://www.w3.org/TR/sparql11-query/#func-ceil
|
10
24
|
# @see https://www.w3.org/TR/xpath-functions/#func-ceil
|
@@ -20,12 +34,21 @@ module SPARQL; module Algebra
|
|
20
34
|
# the operand
|
21
35
|
# @return [RDF::Literal] literal of same type
|
22
36
|
# @raise [TypeError] if the operand is not a numeric value
|
23
|
-
def apply(operand)
|
37
|
+
def apply(operand, **options)
|
24
38
|
case operand
|
25
39
|
when RDF::Literal::Numeric then operand.ceil
|
26
40
|
else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
|
27
41
|
end
|
28
42
|
end
|
43
|
+
|
44
|
+
##
|
45
|
+
#
|
46
|
+
# Returns a partial SPARQL grammar for this operator.
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
def to_sparql(**options)
|
50
|
+
"CEIL(#{operands.to_sparql(**options)})"
|
51
|
+
end
|
29
52
|
end # Ceil
|
30
53
|
end # Operator
|
31
54
|
end; end # SPARQL::Algebra
|
@@ -6,8 +6,13 @@ module SPARQL; module Algebra
|
|
6
6
|
#
|
7
7
|
# The CLEAR operation removes all the triples in the specified graph(s) in the Graph Store.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# [32] Clear ::= 'CLEAR' 'SILENT'? GraphRefAll
|
10
|
+
#
|
11
|
+
# @example SPARQL Grammar
|
12
|
+
# CLEAR SILENT DEFAULT
|
13
|
+
#
|
14
|
+
# @example SSE
|
15
|
+
# (update (clear silent default))
|
11
16
|
#
|
12
17
|
# @see https://www.w3.org/TR/sparql11-update/#clear
|
13
18
|
class Clear < Operator
|
@@ -58,6 +63,15 @@ module SPARQL; module Algebra
|
|
58
63
|
|
59
64
|
queryable
|
60
65
|
end
|
66
|
+
|
67
|
+
##
|
68
|
+
#
|
69
|
+
# Returns a partial SPARQL grammar for this operator.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def to_sparql(**options)
|
73
|
+
"CLEAR " + operands.to_sparql(**options)
|
74
|
+
end
|
61
75
|
end # Clear
|
62
76
|
end # Operator
|
63
77
|
end; end # SPARQL::Algebra
|
@@ -3,17 +3,30 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL `coalesce` function.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
6
|
+
# [121] BuiltInCall ::= ... | 'COALESCE' ExpressionList
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example/>
|
10
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
11
|
+
#
|
12
|
+
# SELECT ?X (SAMPLE(?v) AS ?S)
|
13
|
+
# {
|
14
|
+
# ?s :p ?v .
|
15
|
+
# OPTIONAL { ?s :q ?w }
|
16
|
+
# }
|
17
|
+
# GROUP BY (COALESCE(?w, "1605-11-05"^^xsd:date) AS ?X)
|
18
|
+
#
|
19
|
+
# @example SSE
|
20
|
+
# (prefix
|
21
|
+
# ((: <http://example/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
|
22
|
+
# (project (?X ?S)
|
23
|
+
# (extend ((?S ??.0))
|
24
|
+
# (group
|
25
|
+
# ((?X (coalesce ?w "1605-11-05"^^xsd:date)))
|
26
|
+
# ((??.0 (sample ?v)))
|
27
|
+
# (leftjoin
|
28
|
+
# (bgp (triple ?s :p ?v))
|
29
|
+
# (bgp (triple ?s :q ?w)))))))
|
17
30
|
#
|
18
31
|
# @see https://www.w3.org/TR/sparql11-query/#func-coalesce
|
19
32
|
class Coalesce < Operator
|
@@ -50,6 +63,15 @@ module SPARQL; module Algebra
|
|
50
63
|
end
|
51
64
|
raise TypeError, "None of the operands evaluated"
|
52
65
|
end
|
66
|
+
|
67
|
+
##
|
68
|
+
#
|
69
|
+
# Returns a partial SPARQL grammar for this operator.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def to_sparql(**options)
|
73
|
+
"COALESCE(#{operands.to_sparql(delimiter: ', ', **options)})"
|
74
|
+
end
|
53
75
|
end # Coalesce
|
54
76
|
end # Operator
|
55
77
|
end; end # SPARQL::Algebra
|
@@ -30,62 +30,77 @@ module SPARQL; module Algebra
|
|
30
30
|
# @param [RDF::Literal] right
|
31
31
|
# a literal
|
32
32
|
# @return [RDF::Literal::Integer] `-1`, `0`, or `1`
|
33
|
-
# @raise [TypeError] if either operand is not a
|
34
|
-
def apply(left, right)
|
33
|
+
# @raise [TypeError] if either operand is not a term
|
34
|
+
def apply(left, right, **options)
|
35
|
+
RDF::Literal(spaceship(left, right, **options))
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
#
|
40
|
+
# Returns a partial SPARQL grammar for this operator.
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
def to_sparql(**options)
|
44
|
+
"(#{operands.first.to_sparql(**options)} #{self.class.const_get(:NAME)} #{operands.last.to_sparql(**options)})"
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
# Define <=> as private for recursive statements
|
49
|
+
def spaceship(left, right, **options)
|
35
50
|
case
|
36
51
|
# @see https://www.w3.org/TR/sparql11-query/#OperatorMapping
|
37
52
|
# @see https://www.w3.org/TR/sparql11-query/#modOrderBy
|
38
53
|
when left.is_a?(RDF::Literal) && right.is_a?(RDF::Literal)
|
39
|
-
case
|
40
54
|
# @see https://www.w3.org/TR/xpath-functions/#string-compare
|
41
55
|
# @see https://www.w3.org/TR/xpath-functions/#comp.numeric
|
42
56
|
# @see https://www.w3.org/TR/xpath-functions/#op.boolean
|
43
57
|
# @see https://www.w3.org/TR/xpath-functions/#comp.duration.datetime
|
44
|
-
|
45
|
-
(left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)) ||
|
46
|
-
(left.datatype == right.datatype && left.language == right.language)
|
47
|
-
RDF::Literal(left.send(self.class.const_get(:NAME), right))
|
48
|
-
|
49
|
-
# A plain literal is lower than an RDF literal with type xsd:string of the same lexical form.
|
50
|
-
when left.simple? && right.datatype == RDF::XSD.string && left.value == right.value
|
51
|
-
RDF::Literal(-1)
|
52
|
-
when right.simple? && left.datatype == RDF::XSD.string && right.value == left.value
|
53
|
-
RDF::Literal(-1)
|
54
|
-
|
55
|
-
else
|
56
|
-
left <=> right
|
57
|
-
end
|
58
|
-
|
58
|
+
left <=> right
|
59
59
|
when left.is_a?(RDF::URI) && right.is_a?(RDF::URI)
|
60
|
+
raise TypeError, "Comparing IRIs not supported" unless options[:order_by] || left == right
|
60
61
|
# Pairs of IRIs are ordered by comparing them as simple literals.
|
61
|
-
|
62
|
+
left.to_s <=> right.to_s
|
62
63
|
when left.is_a?(RDF::Node) && right.is_a?(RDF::Node)
|
64
|
+
raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by] || left == right
|
63
65
|
# BNode comparison is undefined.
|
64
|
-
|
66
|
+
left == right ? 0 : 1
|
65
67
|
when left.nil? && right.nil?
|
66
|
-
|
67
|
-
|
68
|
+
0
|
69
|
+
|
70
|
+
when left.is_a?(RDF::Statement) && right.is_a?(RDF::Statement)
|
71
|
+
v = spaceship(left.subject, right.subject, **options)
|
72
|
+
v = spaceship(left.predicate, right.predicate, **options) if v == 0
|
73
|
+
v = spaceship(left.object, right.object, **options) if v == 0
|
74
|
+
v
|
75
|
+
when left.is_a?(RDF::Statement) && right.is_a?(RDF::Term)
|
76
|
+
raise TypeError, "Comparing statement with #{right.inspect}" unless options[:order_by]
|
77
|
+
1
|
78
|
+
when right.is_a?(RDF::Statement) && left.is_a?(RDF::Term)
|
79
|
+
raise TypeError, "Comparing statement with #{left.inspect}" unless options[:order_by]
|
80
|
+
-1
|
81
|
+
|
68
82
|
# SPARQL also fixes an order between some kinds of RDF terms that would not otherwise be ordered:
|
69
83
|
|
70
84
|
when left.nil? && !right.nil?
|
71
|
-
|
85
|
+
-1
|
72
86
|
when right.nil?
|
73
|
-
|
87
|
+
1
|
74
88
|
|
75
89
|
when left.is_a?(RDF::Node) && right.is_a?(RDF::Term)
|
76
|
-
|
90
|
+
raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by]
|
91
|
+
# Nodes lower than other terms
|
92
|
+
-1
|
77
93
|
when right.is_a?(RDF::Node) && left.is_a?(RDF::Term)
|
78
|
-
|
79
|
-
|
80
|
-
when left.is_a?(RDF::Node) && right.is_a?(RDF::URI)
|
81
|
-
RDF::Literal(-1)
|
82
|
-
when right.is_a?(RDF::Node) && left.is_a?(RDF::URI)
|
83
|
-
RDF::Literal(1)
|
94
|
+
raise TypeError, "Comparing Blank nodes not supported" unless options[:order_by]
|
95
|
+
1
|
84
96
|
|
85
97
|
when left.is_a?(RDF::URI) && right.is_a?(RDF::Term)
|
86
|
-
|
98
|
+
raise TypeError, "Comparing IRIs not supported" unless options[:order_by]
|
99
|
+
# IRIs lower than terms other than nodes
|
100
|
+
-1
|
87
101
|
when right.is_a?(RDF::URI) && left.is_a?(RDF::Term)
|
88
|
-
|
102
|
+
raise TypeError, "Comparing IRIs not supported" unless options[:order_by]
|
103
|
+
1
|
89
104
|
else raise TypeError, "expected two RDF::Term operands, but got #{left.inspect} and #{right.inspect}"
|
90
105
|
end
|
91
106
|
end
|
@@ -5,8 +5,23 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# The CONCAT function corresponds to the XPath fn:concat function. The function accepts string literals as arguments.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
8
|
+
# [121] BuiltInCall ::= ... 'CONCAT' ExpressionList
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX : <http://example.org/>
|
12
|
+
# SELECT (CONCAT(?str1,?str2) AS ?str) WHERE {
|
13
|
+
# :s6 :str ?str1 .
|
14
|
+
# :s7 :str ?str2 .
|
15
|
+
# }
|
16
|
+
#
|
17
|
+
# @example SSE
|
18
|
+
# (prefix
|
19
|
+
# ((: <http://example.org/>))
|
20
|
+
# (project (?str)
|
21
|
+
# (extend ((?str (concat ?str1 ?str2)))
|
22
|
+
# (bgp
|
23
|
+
# (triple :s6 :str ?str1)
|
24
|
+
# (triple :s7 :str ?str2)))))
|
10
25
|
#
|
11
26
|
# @see https://www.w3.org/TR/sparql11-query/#func-concat
|
12
27
|
# @see https://www.w3.org/TR/xpath-functions/#func-concat
|
@@ -48,6 +63,15 @@ module SPARQL; module Algebra
|
|
48
63
|
end
|
49
64
|
end
|
50
65
|
end
|
66
|
+
|
67
|
+
##
|
68
|
+
#
|
69
|
+
# Returns a partial SPARQL grammar for this operator.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def to_sparql(**options)
|
73
|
+
"CONCAT(#{operands.to_sparql(delimiter: ', ', **options)})"
|
74
|
+
end
|
51
75
|
end # Concat
|
52
76
|
end # Operator
|
53
77
|
end; end # SPARQL::Algebra
|
@@ -5,12 +5,22 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# The CONSTRUCT query form returns a single RDF graph specified by a graph template. The result is an RDF graph formed by taking each query solution in the solution sequence, substituting for the variables in the graph template, and combining the triples into a single RDF graph by set union.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
8
|
+
# [10] ConstructQuery ::= 'CONSTRUCT' ( ConstructTemplate DatasetClause* WhereClause SolutionModifier | DatasetClause* 'WHERE' '{' TriplesTemplate? '}' SolutionModifier ) ValuesClause
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX : <http://example/>
|
12
|
+
# CONSTRUCT { ?x :p2 ?v }
|
13
|
+
# WHERE {
|
14
|
+
# ?x :p ?o .
|
15
|
+
# OPTIONAL {?o :q ?v }
|
16
|
+
# }
|
17
|
+
#
|
18
|
+
# @example SSE
|
19
|
+
# (prefix ((: <http://example/>))
|
20
|
+
# (construct ((triple ?x :p2 ?v))
|
21
|
+
# (leftjoin
|
22
|
+
# (bgp (triple ?x :p ?o))
|
23
|
+
# (bgp (triple ?o :q ?v)))))
|
14
24
|
#
|
15
25
|
# @see https://www.w3.org/TR/sparql11-query/#construct
|
16
26
|
class Construct < Operator::Binary
|
@@ -52,10 +62,11 @@ module SPARQL; module Algebra
|
|
52
62
|
terms[r] = case o = pattern.send(r)
|
53
63
|
when RDF::Node then nodes[o] ||= RDF::Node.new
|
54
64
|
when RDF::Query::Variable then solution[o]
|
65
|
+
when RDF::Query::Pattern then RDF::Statement.from(o.dup.bind(solution))
|
55
66
|
else o
|
56
67
|
end
|
57
68
|
end
|
58
|
-
|
69
|
+
|
59
70
|
statement = RDF::Statement.from(terms)
|
60
71
|
|
61
72
|
# Sanity checking on statement
|
@@ -80,6 +91,19 @@ module SPARQL; module Algebra
|
|
80
91
|
def query_yields_statements?
|
81
92
|
true
|
82
93
|
end
|
94
|
+
|
95
|
+
##
|
96
|
+
#
|
97
|
+
# Returns a partial SPARQL grammar for this term.
|
98
|
+
#
|
99
|
+
# @return [String]
|
100
|
+
def to_sparql(**options)
|
101
|
+
str = "CONSTRUCT {\n" +
|
102
|
+
operands[0].map { |e| e.to_sparql(as_statement: true, top_level: false, **options) }.join("\n") +
|
103
|
+
"\n}\n"
|
104
|
+
|
105
|
+
str << operands[1].to_sparql(top_level: true, project: nil, **options)
|
106
|
+
end
|
83
107
|
end # Construct
|
84
108
|
end # Operator
|
85
109
|
end; end # SPARQL::Algebra
|
@@ -3,8 +3,21 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# A SPARQL `contains` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [121] BuiltInCall ::= ... | 'CONTAINS' '(' Expression ',' Expression ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example.org/>
|
10
|
+
# SELECT ?s ?str WHERE {
|
11
|
+
# ?s :str ?str
|
12
|
+
# FILTER CONTAINS(?str, "a")
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix
|
17
|
+
# ((: <http://example.org/>))
|
18
|
+
# (project (?s ?str)
|
19
|
+
# (filter (contains ?str "a")
|
20
|
+
# (bgp (triple ?s :str ?str)))))
|
8
21
|
#
|
9
22
|
# @see https://www.w3.org/TR/sparql11-query/#func-contains
|
10
23
|
# @see https://www.w3.org/TR/xpath-functions/#func-contains
|
@@ -31,7 +44,7 @@ module SPARQL; module Algebra
|
|
31
44
|
# a literal
|
32
45
|
# @return [RDF::Literal::Boolean]
|
33
46
|
# @raise [TypeError] if operands are not compatible
|
34
|
-
def apply(left, right)
|
47
|
+
def apply(left, right, **options)
|
35
48
|
case
|
36
49
|
when !left.compatible?(right)
|
37
50
|
raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
|
@@ -39,6 +52,15 @@ module SPARQL; module Algebra
|
|
39
52
|
else RDF::Literal::FALSE
|
40
53
|
end
|
41
54
|
end
|
55
|
+
|
56
|
+
##
|
57
|
+
#
|
58
|
+
# Returns a partial SPARQL grammar for this operator.
|
59
|
+
#
|
60
|
+
# @return [String]
|
61
|
+
def to_sparql(**options)
|
62
|
+
"contains(" + operands.to_sparql(delimiter: ', ', **options) + ")"
|
63
|
+
end
|
42
64
|
end # Contains
|
43
65
|
end # Operator
|
44
66
|
end; end # SPARQL::Algebra
|
@@ -6,8 +6,13 @@ module SPARQL; module Algebra
|
|
6
6
|
#
|
7
7
|
# The COPY operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, but data from the destination graph, if any, is removed before insertion.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# [37] Copy ::= 'COPY' 'SILENT'? GraphOrDefault 'TO' GraphOrDefault
|
10
|
+
#
|
11
|
+
# @example SPARQL Grammar
|
12
|
+
# COPY SILENT GRAPH <http://www.example.com/g1> TO DEFAULT
|
13
|
+
#
|
14
|
+
# @example SSE
|
15
|
+
# (update (copy silent <http://www.example.com/g1> default))
|
11
16
|
#
|
12
17
|
# @see https://www.w3.org/TR/sparql11-update/#copy
|
13
18
|
class Copy < Operator
|
@@ -59,6 +64,18 @@ module SPARQL; module Algebra
|
|
59
64
|
end
|
60
65
|
queryable
|
61
66
|
end
|
67
|
+
|
68
|
+
##
|
69
|
+
#
|
70
|
+
# Returns a partial SPARQL grammar for this operator.
|
71
|
+
#
|
72
|
+
# @return [String]
|
73
|
+
def to_sparql(**options)
|
74
|
+
*args, last = operands.dup
|
75
|
+
args += [:TO, last]
|
76
|
+
|
77
|
+
"COPY " + args.to_sparql(**options)
|
78
|
+
end
|
62
79
|
end # Copy
|
63
80
|
end # Operator
|
64
81
|
end; end # SPARQL::Algebra
|