sparql 3.1.8 → 3.2.3
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 +88 -60
- data/VERSION +1 -1
- data/bin/sparql +15 -35
- data/lib/rack/sparql/conneg.rb +22 -1
- data/lib/sinatra/sparql/extensions.rb +1 -1
- data/lib/sinatra/sparql.rb +57 -12
- data/lib/sparql/algebra/expression.rb +63 -10
- data/lib/sparql/algebra/extensions.rb +110 -46
- data/lib/sparql/algebra/operator/abs.rb +22 -2
- data/lib/sparql/algebra/operator/add.rb +21 -2
- data/lib/sparql/algebra/operator/adjust.rb +69 -0
- 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 +19 -1
- 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 +33 -10
- data/lib/sparql/algebra/operator/bound.rb +22 -1
- data/lib/sparql/algebra/operator/ceil.rb +25 -2
- 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 +9 -0
- 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 +24 -2
- data/lib/sparql/algebra/operator/copy.rb +19 -2
- data/lib/sparql/algebra/operator/count.rb +52 -6
- data/lib/sparql/algebra/operator/create.rb +20 -2
- data/lib/sparql/algebra/operator/dataset.rb +37 -2
- data/lib/sparql/algebra/operator/datatype.rb +25 -6
- data/lib/sparql/algebra/operator/day.rb +25 -7
- 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 +26 -2
- data/lib/sparql/algebra/operator/drop.rb +27 -3
- data/lib/sparql/algebra/operator/encode_for_uri.rb +22 -2
- data/lib/sparql/algebra/operator/equal.rb +12 -2
- 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 +95 -7
- data/lib/sparql/algebra/operator/filter.rb +27 -5
- data/lib/sparql/algebra/operator/floor.rb +25 -2
- 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 +12 -3
- data/lib/sparql/algebra/operator/greater_than_or_equal.rb +12 -2
- data/lib/sparql/algebra/operator/group.rb +133 -8
- data/lib/sparql/algebra/operator/group_concat.rb +43 -7
- data/lib/sparql/algebra/operator/hours.rb +25 -7
- 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 +21 -4
- data/lib/sparql/algebra/operator/is_blank.rb +20 -3
- data/lib/sparql/algebra/operator/is_iri.rb +20 -3
- data/lib/sparql/algebra/operator/is_literal.rb +20 -3
- data/lib/sparql/algebra/operator/is_numeric.rb +22 -5
- data/lib/sparql/algebra/operator/is_triple.rb +32 -0
- data/lib/sparql/algebra/operator/join.rb +58 -3
- data/lib/sparql/algebra/operator/lang.rb +25 -0
- data/lib/sparql/algebra/operator/lang_matches.rb +22 -1
- data/lib/sparql/algebra/operator/lcase.rb +22 -2
- data/lib/sparql/algebra/operator/left_join.rb +44 -3
- data/lib/sparql/algebra/operator/less_than.rb +12 -3
- data/lib/sparql/algebra/operator/less_than_or_equal.rb +12 -2
- data/lib/sparql/algebra/operator/load.rb +25 -2
- data/lib/sparql/algebra/operator/max.rb +19 -1
- data/lib/sparql/algebra/operator/md5.rb +22 -5
- data/lib/sparql/algebra/operator/min.rb +21 -3
- data/lib/sparql/algebra/operator/minus.rb +65 -7
- data/lib/sparql/algebra/operator/minutes.rb +25 -7
- data/lib/sparql/algebra/operator/modify.rb +62 -5
- data/lib/sparql/algebra/operator/month.rb +25 -7
- data/lib/sparql/algebra/operator/move.rb +20 -2
- data/lib/sparql/algebra/operator/multiply.rb +26 -3
- data/lib/sparql/algebra/operator/negate.rb +23 -3
- data/lib/sparql/algebra/operator/not.rb +24 -3
- data/lib/sparql/algebra/operator/not_equal.rb +13 -0
- 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 +24 -5
- data/lib/sparql/algebra/operator/object.rb +32 -0
- data/lib/sparql/algebra/operator/or.rb +26 -3
- data/lib/sparql/algebra/operator/order.rb +64 -1
- data/lib/sparql/algebra/operator/path.rb +29 -2
- data/lib/sparql/algebra/operator/path_opt.rb +28 -65
- data/lib/sparql/algebra/operator/path_plus.rb +37 -10
- data/lib/sparql/algebra/operator/path_range.rb +178 -0
- data/lib/sparql/algebra/operator/path_star.rb +25 -4
- data/lib/sparql/algebra/operator/path_zero.rb +110 -0
- data/lib/sparql/algebra/operator/plus.rb +49 -8
- data/lib/sparql/algebra/operator/predicate.rb +32 -0
- data/lib/sparql/algebra/operator/prefix.rb +24 -3
- data/lib/sparql/algebra/operator/project.rb +111 -6
- data/lib/sparql/algebra/operator/rand.rb +30 -2
- data/lib/sparql/algebra/operator/reduced.rb +20 -3
- data/lib/sparql/algebra/operator/regex.rb +26 -18
- data/lib/sparql/algebra/operator/replace.rb +26 -6
- data/lib/sparql/algebra/operator/reverse.rb +31 -2
- data/lib/sparql/algebra/operator/round.rb +25 -2
- data/lib/sparql/algebra/operator/same_term.rb +24 -6
- data/lib/sparql/algebra/operator/sample.rb +32 -8
- data/lib/sparql/algebra/operator/seconds.rb +25 -7
- data/lib/sparql/algebra/operator/seq.rb +23 -5
- data/lib/sparql/algebra/operator/sequence.rb +14 -11
- data/lib/sparql/algebra/operator/sha1.rb +18 -1
- data/lib/sparql/algebra/operator/sha256.rb +18 -1
- data/lib/sparql/algebra/operator/sha384.rb +18 -1
- data/lib/sparql/algebra/operator/sha512.rb +18 -1
- data/lib/sparql/algebra/operator/slice.rb +27 -5
- data/lib/sparql/algebra/operator/str.rb +21 -1
- data/lib/sparql/algebra/operator/strafter.rb +25 -2
- data/lib/sparql/algebra/operator/strbefore.rb +25 -2
- data/lib/sparql/algebra/operator/strdt.rb +22 -1
- data/lib/sparql/algebra/operator/strends.rb +25 -3
- data/lib/sparql/algebra/operator/strlang.rb +24 -6
- data/lib/sparql/algebra/operator/strlen.rb +23 -2
- data/lib/sparql/algebra/operator/strstarts.rb +25 -2
- data/lib/sparql/algebra/operator/struuid.rb +29 -9
- data/lib/sparql/algebra/operator/subject.rb +32 -0
- data/lib/sparql/algebra/operator/substr.rb +23 -2
- data/lib/sparql/algebra/operator/subtract.rb +37 -7
- data/lib/sparql/algebra/operator/sum.rb +24 -6
- data/lib/sparql/algebra/operator/table.rb +85 -4
- data/lib/sparql/algebra/operator/timezone.rb +25 -7
- data/lib/sparql/algebra/operator/triple.rb +24 -0
- data/lib/sparql/algebra/operator/tz.rb +24 -7
- data/lib/sparql/algebra/operator/ucase.rb +23 -2
- 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 +27 -8
- data/lib/sparql/algebra/operator/with.rb +38 -4
- data/lib/sparql/algebra/operator/year.rb +25 -7
- data/lib/sparql/algebra/operator.rb +150 -12
- data/lib/sparql/algebra/query.rb +5 -3
- data/lib/sparql/algebra/sxp_extensions.rb +3 -3
- data/lib/sparql/algebra.rb +42 -6
- data/lib/sparql/grammar/meta.rb +1367 -267
- data/lib/sparql/grammar/parser11.rb +829 -331
- data/lib/sparql/grammar/terminals11.rb +2 -2
- data/lib/sparql/grammar.rb +6 -4
- data/lib/sparql/results.rb +3 -2
- data/lib/sparql/server.rb +93 -0
- data/lib/sparql.rb +8 -5
- metadata +57 -35
@@ -5,12 +5,23 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# There is a filter operator EXISTS that takes a graph pattern. EXISTS returns `true`/`false` depending on whether the pattern matches the dataset given the bindings in the current group graph pattern, the dataset and the active graph at this point in the query evaluation. No additional binding of variables occurs. The `NOT EXISTS` form translates into `fn:not(EXISTS{...})`.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
8
|
+
# [126] NotExistsFunc ::= 'NOT' 'EXISTS' GroupGraphPattern
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX ex: <http://www.w3.org/2009/sparql/docs/tests/data-sparql11/negation#>
|
12
|
+
# SELECT ?animal {
|
13
|
+
# ?animal a ex:Animal
|
14
|
+
# FILTER NOT EXISTS { ?animal a ex:Insect }
|
15
|
+
# }
|
16
|
+
#
|
17
|
+
# @example SSE
|
18
|
+
# (prefix
|
19
|
+
# ((ex: <http://www.w3.org/2009/sparql/docs/tests/data-sparql11/negation#>))
|
20
|
+
# (project (?animal)
|
21
|
+
# (filter
|
22
|
+
# (notexists
|
23
|
+
# (bgp (triple ?animal a ex:Insect)))
|
24
|
+
# (bgp (triple ?animal a ex:Animal)))) )
|
14
25
|
#
|
15
26
|
# @see https://www.w3.org/TR/sparql11-query/#func-abs
|
16
27
|
# @see https://www.w3.org/TR/xpath-functions/#func-abs
|
@@ -34,6 +45,19 @@ module SPARQL; module Algebra
|
|
34
45
|
queryable = options[:queryable]
|
35
46
|
operand(0).execute(queryable, solutions: solutions, **options).empty?
|
36
47
|
end
|
48
|
+
|
49
|
+
##
|
50
|
+
#
|
51
|
+
# Returns a partial SPARQL grammar for this operator.
|
52
|
+
#
|
53
|
+
# @param [Boolean] top_level (true)
|
54
|
+
# Treat this as a top-level, generating SELECT ... WHERE {}
|
55
|
+
# @return [String]
|
56
|
+
def to_sparql(top_level: true, **options)
|
57
|
+
"NOT EXISTS {\n" +
|
58
|
+
operands.last.to_sparql(top_level: false, **options) +
|
59
|
+
"\n}"
|
60
|
+
end
|
37
61
|
end # NotExists
|
38
62
|
end # Operator
|
39
63
|
end; end # SPARQL::Algebra
|
@@ -5,8 +5,13 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# Used for filters with more than one expression.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
8
|
+
# [114] RelationalExpression ::= NumericExpression ('NOT' 'IN' ExpressionList)?
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# ASK { FILTER(2 NOT IN ()) }
|
12
|
+
#
|
13
|
+
# @example SSE
|
14
|
+
# (ask (filter (notin 2) (bgp)))
|
10
15
|
#
|
11
16
|
# @see https://www.w3.org/TR/sparql11-query/#func-notin
|
12
17
|
class NotIn < Operator
|
@@ -58,6 +63,18 @@ module SPARQL; module Algebra
|
|
58
63
|
else RDF::Literal::TRUE
|
59
64
|
end
|
60
65
|
end
|
61
|
-
|
66
|
+
|
67
|
+
##
|
68
|
+
#
|
69
|
+
# Returns a partial SPARQL grammar for this operator.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def to_sparql(**options)
|
73
|
+
"(" + operands.first.to_sparql(**options) +
|
74
|
+
" NOT IN (" +
|
75
|
+
operands[1..-1].map {|e| e.to_sparql(**options)}.join(", ") +
|
76
|
+
"))"
|
77
|
+
end
|
78
|
+
end # NotIn
|
62
79
|
end # Operator
|
63
80
|
end; end # SPARQL::Algebra
|
@@ -3,8 +3,18 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL Property Path `notoneof` (NegatedPropertySet) operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [96] PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX ex: <http://www.example.org/schema#>
|
10
|
+
# PREFIX in: <http://www.example.org/instance#>
|
11
|
+
# ASK { in:a !(ex:p1|ex:p2) ?x }
|
12
|
+
#
|
13
|
+
# @example SSE
|
14
|
+
# (prefix ((ex: <http://www.example.org/schema#>)
|
15
|
+
# (in: <http://www.example.org/instance#>))
|
16
|
+
# (ask
|
17
|
+
# (path in:a (notoneof ex:p1 ex:p2) ?x)))
|
8
18
|
#
|
9
19
|
# @see https://www.w3.org/TR/sparql11-query/#eval_negatedPropertySet
|
10
20
|
class NotOneOf < Operator
|
@@ -46,6 +56,15 @@ module SPARQL; module Algebra
|
|
46
56
|
block.call(solution)
|
47
57
|
end
|
48
58
|
end
|
59
|
+
|
60
|
+
##
|
61
|
+
#
|
62
|
+
# Returns a partial SPARQL grammar for this operator.
|
63
|
+
#
|
64
|
+
# @return [String]
|
65
|
+
def to_sparql(**options)
|
66
|
+
"!(" + operands.to_sparql(delimiter: ' | ', **options) + ')'
|
67
|
+
end
|
49
68
|
end # NotOneOf
|
50
69
|
end # Operator
|
51
70
|
end; end # SPARQL::Algebra
|
@@ -7,11 +7,21 @@ module SPARQL; module Algebra
|
|
7
7
|
#
|
8
8
|
# Returns an XSD dateTime value for the current query execution. All calls to this function in any one query execution must return the same value. The exact moment returned is not specified.
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# [121] BuiltInCall ::= ... | 'NOW' NIL
|
11
|
+
#
|
12
|
+
# @example SPARQL Grammar
|
13
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
14
|
+
# ASK {
|
15
|
+
# BIND(NOW() AS ?n)
|
16
|
+
# FILTER(DATATYPE(?n) = xsd:dateTime)
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example SSE
|
20
|
+
# (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>))
|
21
|
+
# (ask
|
22
|
+
# (filter (= (datatype ?n) xsd:dateTime)
|
23
|
+
# (extend ((?n (now)))
|
24
|
+
# (bgp)))))
|
15
25
|
#
|
16
26
|
# @see https://www.w3.org/TR/sparql11-query/#func-now
|
17
27
|
class Now < Operator::Nullary
|
@@ -26,6 +36,15 @@ module SPARQL; module Algebra
|
|
26
36
|
def apply(**options)
|
27
37
|
RDF::Literal(DateTime.now)
|
28
38
|
end
|
39
|
+
|
40
|
+
##
|
41
|
+
#
|
42
|
+
# Returns a partial SPARQL grammar for this operator.
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
def to_sparql(**options)
|
46
|
+
"NOW()"
|
47
|
+
end
|
29
48
|
end # Now
|
30
49
|
end # Operator
|
31
50
|
end; end # SPARQL::Algebra
|
@@ -5,6 +5,29 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# If triple is an RDF-star triple, the function returns the object of this triple. Passing anything other than an RDF-star triple is an error.
|
7
7
|
#
|
8
|
+
# [121] BuiltInCall ::= ... | 'OBJECT' '(' Expression ')'
|
9
|
+
#
|
10
|
+
# @example SPARQL Grammar
|
11
|
+
# PREFIX : <http://example.com/ns#>
|
12
|
+
# SELECT * {
|
13
|
+
# ?t :source :g
|
14
|
+
# FILTER(isTriple(?t))
|
15
|
+
# FILTER(SUBJECT(?t) = :s)
|
16
|
+
# FILTER(PREDICATE(?t) = :p)
|
17
|
+
# FILTER(OBJECT(?t) = :o)
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
# @example SSE
|
21
|
+
# (prefix
|
22
|
+
# ((: <http://example.com/ns#>))
|
23
|
+
# (filter
|
24
|
+
# (exprlist
|
25
|
+
# (isTRIPLE ?t)
|
26
|
+
# (= (subject ?t) :s)
|
27
|
+
# (= (predicate ?t) :p)
|
28
|
+
# (= (object ?t) :o))
|
29
|
+
# (bgp (triple ?t :source :g))) )
|
30
|
+
#
|
8
31
|
# @see https://w3c.github.io/rdf-star/rdf-star-cg-spec.html#object
|
9
32
|
class Object < Operator::Unary
|
10
33
|
include Evaluatable
|
@@ -22,6 +45,15 @@ module SPARQL; module Algebra
|
|
22
45
|
raise TypeError, "expected an RDF::Statement, but got #{operand.inspect}" unless operand.is_a?(RDF::Statement)
|
23
46
|
operand.object
|
24
47
|
end
|
48
|
+
|
49
|
+
##
|
50
|
+
#
|
51
|
+
# Returns a partial SPARQL grammar for this operator.
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
def to_sparql(**options)
|
55
|
+
"OBJECT(" + operands.last.to_sparql(**options) + ")"
|
56
|
+
end
|
25
57
|
end # Object
|
26
58
|
end # Operator
|
27
59
|
end; end # SPARQL::Algebra
|
@@ -3,9 +3,23 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL logical `or` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# [111] ConditionalOrExpression ::= ConditionalAndExpression ( '||' ConditionalAndExpression )*
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
10
|
+
# PREFIX : <http://example.org/ns#>
|
11
|
+
# SELECT ?a
|
12
|
+
# WHERE {
|
13
|
+
# ?a :p ?v .
|
14
|
+
# FILTER ("false"^^xsd:boolean || ?v) .
|
15
|
+
# }
|
16
|
+
#
|
17
|
+
# @example SSE
|
18
|
+
# (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
|
19
|
+
# (: <http://example.org/ns#>))
|
20
|
+
# (project (?a)
|
21
|
+
# (filter (|| false ?v)
|
22
|
+
# (bgp (triple ?a :p ?v)))))
|
9
23
|
#
|
10
24
|
# @see https://www.w3.org/TR/sparql11-query/#func-logical-or
|
11
25
|
# @see https://www.w3.org/TR/sparql11-query/#evaluation
|
@@ -63,6 +77,15 @@ module SPARQL; module Algebra
|
|
63
77
|
else RDF::Literal(left || right)
|
64
78
|
end
|
65
79
|
end
|
80
|
+
|
81
|
+
##
|
82
|
+
#
|
83
|
+
# Returns a partial SPARQL grammar for this operator.
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
def to_sparql(**options)
|
87
|
+
"(#{operands.first.to_sparql(**options)} || #{operands.last.to_sparql(**options)})"
|
88
|
+
end
|
66
89
|
end # Or
|
67
90
|
end # Operator
|
68
91
|
end; end # SPARQL::Algebra
|
@@ -3,12 +3,64 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL GraphPattern `order` operator.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# [23] OrderClause ::= 'ORDER' 'BY' OrderCondition+
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX foaf: <http://xmlns.com/foaf/0.1/>
|
10
|
+
# SELECT ?name
|
11
|
+
# WHERE { ?x foaf:name ?name }
|
12
|
+
# ORDER BY ASC(?name)
|
13
|
+
#
|
14
|
+
# @example SSE
|
7
15
|
# (prefix ((foaf: <http://xmlns.com/foaf/0.1/>))
|
8
16
|
# (project (?name)
|
9
17
|
# (order ((asc ?name))
|
10
18
|
# (bgp (triple ?x foaf:name ?name)))))
|
11
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
|
+
#
|
12
64
|
# @see https://www.w3.org/TR/sparql11-query/#modOrderBy
|
13
65
|
class Order < Operator::Binary
|
14
66
|
include Query
|
@@ -56,6 +108,17 @@ module SPARQL; module Algebra
|
|
56
108
|
@solutions.each(&block) if block_given?
|
57
109
|
@solutions
|
58
110
|
end
|
111
|
+
|
112
|
+
##
|
113
|
+
#
|
114
|
+
# Returns a partial SPARQL grammar for this operator.
|
115
|
+
#
|
116
|
+
# Provides order to descendant query.
|
117
|
+
#
|
118
|
+
# @return [String]
|
119
|
+
def to_sparql(**options)
|
120
|
+
operands.last.to_sparql(order_ops: operands.first, **options)
|
121
|
+
end
|
59
122
|
end # Order
|
60
123
|
end # Operator
|
61
124
|
end; end # SPARQL::Algebra
|
@@ -3,8 +3,23 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL Property Path `path` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [88] Path ::= PathAlternative
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://www.example.org/>
|
10
|
+
# SELECT ?t
|
11
|
+
# WHERE {
|
12
|
+
# :a :p1|:p2/:p3|:p4 ?t
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://www.example.org/>))
|
17
|
+
# (project (?t)
|
18
|
+
# (path :a
|
19
|
+
# (alt
|
20
|
+
# (alt :p1 (seq :p2 :p3))
|
21
|
+
# :p4)
|
22
|
+
# ?t)))
|
8
23
|
#
|
9
24
|
# @see https://www.w3.org/TR/sparql11-query/#sparqlTranslatePathExpressions
|
10
25
|
class Path < Operator::Ternary
|
@@ -45,6 +60,18 @@ module SPARQL; module Algebra
|
|
45
60
|
@solutions.each(&block) if block_given?
|
46
61
|
@solutions
|
47
62
|
end
|
63
|
+
|
64
|
+
##
|
65
|
+
#
|
66
|
+
# Returns a partial SPARQL grammar for this operator.
|
67
|
+
#
|
68
|
+
# @param [Boolean] top_level (true)
|
69
|
+
# Treat this as a top-level, generating SELECT ... WHERE {}
|
70
|
+
# @return [String]
|
71
|
+
def to_sparql(top_level: true, **options)
|
72
|
+
str = operands.to_sparql(top_level: false, **options) + " ."
|
73
|
+
top_level ? Operator.to_sparql(str, **options) : str
|
74
|
+
end
|
48
75
|
end # Path
|
49
76
|
end # Operator
|
50
77
|
end; end # SPARQL::Algebra
|
@@ -3,8 +3,18 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL Property Path `path?` (ZeroOrOnePath) operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [91] PathElt ::= PathPrimary PathMod?
|
7
|
+
# [93] PathMod ::= '*' | '?' | '+' | '{' INTEGER? (',' INTEGER?)? '}'
|
8
|
+
|
9
|
+
# @example SPARQL Grammar
|
10
|
+
# PREFIX : <http://example/>
|
11
|
+
# SELECT * WHERE {
|
12
|
+
# :a (:p/:p)? ?t
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example/>))
|
17
|
+
# (path :a (path? (seq :p :p)) ?t))
|
8
18
|
#
|
9
19
|
# @see https://www.w3.org/TR/sparql11-query/#defn_evalPP_ZeroOrOnePath
|
10
20
|
class PathOpt < Operator::Unary
|
@@ -13,11 +23,10 @@ module SPARQL; module Algebra
|
|
13
23
|
NAME = :path?
|
14
24
|
|
15
25
|
##
|
16
|
-
#
|
26
|
+
# Optional path:
|
17
27
|
#
|
18
28
|
# (path x (path? :p) y)
|
19
|
-
# => (union (bgp ((x :p y))) (filter (x =
|
20
|
-
#
|
29
|
+
# => (union (bgp ((x :p y))) (filter (x = y) (solution x y)))
|
21
30
|
#
|
22
31
|
# @param [RDF::Queryable] queryable
|
23
32
|
# the graph or repository to query
|
@@ -34,79 +43,33 @@ module SPARQL; module Algebra
|
|
34
43
|
subject, object = options[:subject], options[:object]
|
35
44
|
debug(options) {"Path? #{[subject, operands, object].to_sse}"}
|
36
45
|
|
37
|
-
|
38
|
-
|
39
|
-
case
|
40
|
-
when subject.variable? && object.variable?
|
41
|
-
# Nodes is the set of all subjects and objects in queryable
|
42
|
-
# FIXME: should this be Queryable#enum_nodes?
|
43
|
-
# All subjects which are `object`
|
44
|
-
query = RDF::Query.new {|q| q.pattern({subject: subject})}
|
45
|
-
queryable.query(query, **options) do |solution|
|
46
|
-
solution.merge!(object.to_sym => solution[subject])
|
47
|
-
debug(options) {"(solution-s0)-> #{solution.to_h.to_sse}"}
|
48
|
-
solutions << solution
|
49
|
-
end if query.valid?
|
50
|
-
|
51
|
-
# All objects which are `object`
|
52
|
-
query = RDF::Query.new {|q| q.pattern({object: object})}
|
53
|
-
queryable.query(query, **options) do |solution|
|
54
|
-
solution.merge!(subject.to_sym => solution[object])
|
55
|
-
debug(options) {"(solution-o0)-> #{solution.to_h.to_sse}"}
|
56
|
-
solutions << solution
|
57
|
-
end if query.valid?
|
58
|
-
when subject.variable?
|
59
|
-
# All subjects which are `object`
|
60
|
-
query = RDF::Query.new {|q| q.pattern({subject: object})}
|
61
|
-
queryable.query(query, **options) do |solution|
|
62
|
-
solution.merge!(subject.to_sym => object)
|
63
|
-
debug(options) {"(solution-s0)-> #{solution.to_h.to_sse}"}
|
64
|
-
solutions << solution
|
65
|
-
end if query.valid?
|
66
|
-
|
67
|
-
# All objects which are `object`
|
68
|
-
query = RDF::Query.new {|q| q.pattern({object: object})}
|
69
|
-
queryable.query(query, **options) do |solution|
|
70
|
-
solution.merge!(subject.to_sym => object)
|
71
|
-
debug(options) {"(solution-o0)-> #{solution.to_h.to_sse}"}
|
72
|
-
solutions << solution
|
73
|
-
end if query.valid?
|
74
|
-
when object.variable?
|
75
|
-
# All subjects which are `subject`
|
76
|
-
query = RDF::Query.new {|q| q.pattern({subject: subject})}
|
77
|
-
queryable.query(query, **options) do |solution|
|
78
|
-
solution.merge!(object.to_sym => subject)
|
79
|
-
debug(options) {"(solution-s0)-> #{solution.to_h.to_sse}"}
|
80
|
-
solutions << solution
|
81
|
-
end if query.valid?
|
82
|
-
|
83
|
-
# All objects which are `subject
|
84
|
-
query = RDF::Query.new {|q| q.pattern({object: subject})}
|
85
|
-
queryable.query(query, **options) do |solution|
|
86
|
-
solution.merge!(object.to_sym => subject)
|
87
|
-
debug(options) {"(solution-o0)-> #{solution.to_h.to_sse}"}
|
88
|
-
solutions << solution
|
89
|
-
end if query.valid?
|
90
|
-
else
|
91
|
-
# Otherwise, if subject == object, an empty solution
|
92
|
-
solutions << RDF::Query::Solution.new if subject == object
|
93
|
-
end
|
46
|
+
query = PathZero.new(operand)
|
47
|
+
solutions = query.execute(queryable, **options.merge(depth: options[:depth].to_i + 1))
|
94
48
|
|
95
49
|
# Solutions where predicate exists
|
96
50
|
query = if operand.is_a?(RDF::Term)
|
97
51
|
RDF::Query.new do |q|
|
98
52
|
q.pattern [subject, operand, object]
|
99
53
|
end
|
100
|
-
else
|
54
|
+
else # path
|
101
55
|
operand
|
102
56
|
end
|
103
57
|
|
104
58
|
# Recurse into query
|
105
|
-
solutions +=
|
106
|
-
|
59
|
+
solutions += query.execute(queryable, **options.merge(depth: options[:depth].to_i + 1))
|
60
|
+
debug(options) {"(path?)=> #{solutions.to_sxp}"}
|
107
61
|
solutions.each(&block) if block_given?
|
108
62
|
solutions
|
109
63
|
end
|
64
|
+
|
65
|
+
##
|
66
|
+
#
|
67
|
+
# Returns a partial SPARQL grammar for this operator.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
def to_sparql(**options)
|
71
|
+
"(#{operands.first.to_sparql(**options)})?"
|
72
|
+
end
|
110
73
|
end # PathOpt
|
111
74
|
end # Operator
|
112
75
|
end; end # SPARQL::Algebra
|
@@ -3,8 +3,18 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL Property Path `path+` (OneOrMorePath) operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [91] PathElt ::= PathPrimary PathMod?
|
7
|
+
# [93] PathMod ::= '*' | '?' | '+' | '{' INTEGER? (',' INTEGER?)? '}'
|
8
|
+
|
9
|
+
# @example SPARQL Grammar
|
10
|
+
# PREFIX : <http://example/>
|
11
|
+
# SELECT * WHERE {
|
12
|
+
# :a :p+ ?z
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example/>))
|
17
|
+
# (path :a (path+ :p) ?z))
|
8
18
|
#
|
9
19
|
# @see https://www.w3.org/TR/sparql11-query/#defn_evalPP_OneOrMorePath
|
10
20
|
class PathPlus < Operator::Unary
|
@@ -15,6 +25,16 @@ module SPARQL; module Algebra
|
|
15
25
|
##
|
16
26
|
# Match on simple relation of subject to object, and then recurse on solutions
|
17
27
|
#
|
28
|
+
# Path including at least one:
|
29
|
+
#
|
30
|
+
# (path :a (path+ :p) :b)
|
31
|
+
#
|
32
|
+
# into
|
33
|
+
#
|
34
|
+
# (union
|
35
|
+
# (bgp (triple :a :p :b))
|
36
|
+
# (path :a (path* :p) :b))
|
37
|
+
#
|
18
38
|
# @param [RDF::Queryable] queryable
|
19
39
|
# the graph or repository to query
|
20
40
|
# @param [Hash{Symbol => Object}] options
|
@@ -52,10 +72,8 @@ module SPARQL; module Algebra
|
|
52
72
|
|
53
73
|
# Keep track of solutions
|
54
74
|
# Recurse into query
|
55
|
-
immediate_solutions =
|
56
|
-
|
57
|
-
immediate_solutions << solution
|
58
|
-
end
|
75
|
+
immediate_solutions =
|
76
|
+
query.execute(queryable, depth: options[:depth].to_i + 1, **options)
|
59
77
|
|
60
78
|
# For all solutions, if they are not in the accumulator, add them and recurse, otherwise skip
|
61
79
|
recursive_solutions = RDF::Query::Solutions.new
|
@@ -66,23 +84,23 @@ module SPARQL; module Algebra
|
|
66
84
|
case
|
67
85
|
when subject.variable? && object.variable?
|
68
86
|
# Query starting with bound object as subject, but replace result with subject
|
69
|
-
rs =
|
87
|
+
rs = self.execute(queryable, **options.merge(
|
70
88
|
subject: solution[object],
|
71
89
|
accumulator: (cumulative_solutions + immediate_solutions),
|
72
90
|
depth: options[:depth].to_i + 1)).map {|s| s.merge(subject.to_sym => solution[subject])}
|
73
91
|
# Query starting with bound subject as object, but replace result with subject
|
74
|
-
ro =
|
92
|
+
ro = self.execute(queryable, **options.merge(
|
75
93
|
object: solution[subject],
|
76
94
|
accumulator: (cumulative_solutions + immediate_solutions),
|
77
95
|
depth: options[:depth].to_i + 1)).map {|s| s.merge(object.to_sym => solution[object])}
|
78
96
|
recursive_solutions += (rs + ro).uniq
|
79
97
|
when subject.variable?
|
80
|
-
recursive_solutions +=
|
98
|
+
recursive_solutions += self.execute(queryable, **options.merge(
|
81
99
|
object: solution[subject],
|
82
100
|
accumulator: (cumulative_solutions + immediate_solutions),
|
83
101
|
depth: options[:depth].to_i + 1)).uniq
|
84
102
|
when object.variable?
|
85
|
-
recursive_solutions +=
|
103
|
+
recursive_solutions += self.execute(queryable, **options.merge(
|
86
104
|
subject: solution[object],
|
87
105
|
accumulator: (cumulative_solutions + immediate_solutions),
|
88
106
|
depth: options[:depth].to_i + 1)).uniq
|
@@ -94,6 +112,15 @@ module SPARQL; module Algebra
|
|
94
112
|
solutions.each(&block) if block_given? # Only at top-level
|
95
113
|
solutions
|
96
114
|
end
|
115
|
+
|
116
|
+
##
|
117
|
+
#
|
118
|
+
# Returns a partial SPARQL grammar for this operator.
|
119
|
+
#
|
120
|
+
# @return [String]
|
121
|
+
def to_sparql(**options)
|
122
|
+
"(#{operands.first.to_sparql(**options)})+"
|
123
|
+
end
|
97
124
|
end # PathPlus
|
98
125
|
end # Operator
|
99
126
|
end; end # SPARQL::Algebra
|