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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -22
  3. data/VERSION +1 -1
  4. data/bin/sparql +14 -4
  5. data/lib/sparql/algebra/aggregate.rb +1 -1
  6. data/lib/sparql/algebra/evaluatable.rb +4 -4
  7. data/lib/sparql/algebra/expression.rb +28 -3
  8. data/lib/sparql/algebra/extensions.rb +109 -45
  9. data/lib/sparql/algebra/operator/abs.rb +23 -3
  10. data/lib/sparql/algebra/operator/add.rb +21 -2
  11. data/lib/sparql/algebra/operator/alt.rb +26 -2
  12. data/lib/sparql/algebra/operator/and.rb +25 -3
  13. data/lib/sparql/algebra/operator/asc.rb +20 -1
  14. data/lib/sparql/algebra/operator/ask.rb +17 -1
  15. data/lib/sparql/algebra/operator/avg.rb +20 -2
  16. data/lib/sparql/algebra/operator/base.rb +18 -1
  17. data/lib/sparql/algebra/operator/bgp.rb +13 -1
  18. data/lib/sparql/algebra/operator/bnode.rb +34 -11
  19. data/lib/sparql/algebra/operator/bound.rb +22 -1
  20. data/lib/sparql/algebra/operator/ceil.rb +26 -3
  21. data/lib/sparql/algebra/operator/clear.rb +26 -2
  22. data/lib/sparql/algebra/operator/coalesce.rb +33 -11
  23. data/lib/sparql/algebra/operator/compare.rb +48 -40
  24. data/lib/sparql/algebra/operator/concat.rb +26 -2
  25. data/lib/sparql/algebra/operator/construct.rb +29 -6
  26. data/lib/sparql/algebra/operator/contains.rb +25 -3
  27. data/lib/sparql/algebra/operator/copy.rb +19 -2
  28. data/lib/sparql/algebra/operator/count.rb +53 -7
  29. data/lib/sparql/algebra/operator/create.rb +20 -2
  30. data/lib/sparql/algebra/operator/dataset.rb +27 -2
  31. data/lib/sparql/algebra/operator/datatype.rb +26 -7
  32. data/lib/sparql/algebra/operator/day.rb +24 -6
  33. data/lib/sparql/algebra/operator/delete.rb +29 -2
  34. data/lib/sparql/algebra/operator/delete_data.rb +23 -2
  35. data/lib/sparql/algebra/operator/delete_where.rb +24 -2
  36. data/lib/sparql/algebra/operator/desc.rb +20 -1
  37. data/lib/sparql/algebra/operator/describe.rb +27 -4
  38. data/lib/sparql/algebra/operator/distinct.rb +20 -3
  39. data/lib/sparql/algebra/operator/divide.rb +27 -3
  40. data/lib/sparql/algebra/operator/drop.rb +27 -3
  41. data/lib/sparql/algebra/operator/encode_for_uri.rb +23 -3
  42. data/lib/sparql/algebra/operator/equal.rb +13 -3
  43. data/lib/sparql/algebra/operator/exists.rb +28 -4
  44. data/lib/sparql/algebra/operator/exprlist.rb +15 -2
  45. data/lib/sparql/algebra/operator/extend.rb +64 -6
  46. data/lib/sparql/algebra/operator/filter.rb +27 -5
  47. data/lib/sparql/algebra/operator/floor.rb +26 -3
  48. data/lib/sparql/algebra/operator/function_call.rb +64 -0
  49. data/lib/sparql/algebra/operator/graph.rb +69 -6
  50. data/lib/sparql/algebra/operator/greater_than.rb +14 -4
  51. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +14 -4
  52. data/lib/sparql/algebra/operator/group.rb +105 -8
  53. data/lib/sparql/algebra/operator/group_concat.rb +44 -8
  54. data/lib/sparql/algebra/operator/hours.rb +24 -6
  55. data/lib/sparql/algebra/operator/if.rb +20 -3
  56. data/lib/sparql/algebra/operator/in.rb +18 -1
  57. data/lib/sparql/algebra/operator/insert.rb +24 -2
  58. data/lib/sparql/algebra/operator/insert_data.rb +23 -2
  59. data/lib/sparql/algebra/operator/iri.rb +22 -5
  60. data/lib/sparql/algebra/operator/is_blank.rb +21 -4
  61. data/lib/sparql/algebra/operator/is_iri.rb +21 -4
  62. data/lib/sparql/algebra/operator/is_literal.rb +21 -4
  63. data/lib/sparql/algebra/operator/is_numeric.rb +23 -6
  64. data/lib/sparql/algebra/operator/is_triple.rb +33 -1
  65. data/lib/sparql/algebra/operator/join.rb +56 -1
  66. data/lib/sparql/algebra/operator/lang.rb +26 -1
  67. data/lib/sparql/algebra/operator/lang_matches.rb +23 -2
  68. data/lib/sparql/algebra/operator/lcase.rb +23 -3
  69. data/lib/sparql/algebra/operator/left_join.rb +42 -1
  70. data/lib/sparql/algebra/operator/less_than.rb +14 -4
  71. data/lib/sparql/algebra/operator/less_than_or_equal.rb +14 -4
  72. data/lib/sparql/algebra/operator/load.rb +25 -2
  73. data/lib/sparql/algebra/operator/max.rb +20 -2
  74. data/lib/sparql/algebra/operator/md5.rb +23 -6
  75. data/lib/sparql/algebra/operator/min.rb +22 -4
  76. data/lib/sparql/algebra/operator/minus.rb +65 -7
  77. data/lib/sparql/algebra/operator/minutes.rb +24 -6
  78. data/lib/sparql/algebra/operator/modify.rb +41 -5
  79. data/lib/sparql/algebra/operator/month.rb +24 -6
  80. data/lib/sparql/algebra/operator/move.rb +20 -2
  81. data/lib/sparql/algebra/operator/multiply.rb +27 -4
  82. data/lib/sparql/algebra/operator/negate.rb +24 -4
  83. data/lib/sparql/algebra/operator/not.rb +25 -4
  84. data/lib/sparql/algebra/operator/not_equal.rb +16 -1
  85. data/lib/sparql/algebra/operator/notexists.rb +30 -6
  86. data/lib/sparql/algebra/operator/notin.rb +20 -3
  87. data/lib/sparql/algebra/operator/notoneof.rb +21 -2
  88. data/lib/sparql/algebra/operator/now.rb +25 -6
  89. data/lib/sparql/algebra/operator/object.rb +33 -1
  90. data/lib/sparql/algebra/operator/or.rb +26 -3
  91. data/lib/sparql/algebra/operator/order.rb +71 -2
  92. data/lib/sparql/algebra/operator/path.rb +29 -2
  93. data/lib/sparql/algebra/operator/path_opt.rb +21 -2
  94. data/lib/sparql/algebra/operator/path_plus.rb +21 -2
  95. data/lib/sparql/algebra/operator/path_star.rb +20 -2
  96. data/lib/sparql/algebra/operator/plus.rb +43 -4
  97. data/lib/sparql/algebra/operator/predicate.rb +33 -1
  98. data/lib/sparql/algebra/operator/prefix.rb +24 -3
  99. data/lib/sparql/algebra/operator/project.rb +69 -5
  100. data/lib/sparql/algebra/operator/rand.rb +31 -3
  101. data/lib/sparql/algebra/operator/reduced.rb +20 -3
  102. data/lib/sparql/algebra/operator/regex.rb +27 -19
  103. data/lib/sparql/algebra/operator/replace.rb +27 -7
  104. data/lib/sparql/algebra/operator/reverse.rb +31 -2
  105. data/lib/sparql/algebra/operator/round.rb +26 -3
  106. data/lib/sparql/algebra/operator/same_term.rb +25 -7
  107. data/lib/sparql/algebra/operator/sample.rb +33 -9
  108. data/lib/sparql/algebra/operator/seconds.rb +24 -6
  109. data/lib/sparql/algebra/operator/seq.rb +20 -2
  110. data/lib/sparql/algebra/operator/sequence.rb +4 -11
  111. data/lib/sparql/algebra/operator/sha1.rb +19 -2
  112. data/lib/sparql/algebra/operator/sha256.rb +19 -2
  113. data/lib/sparql/algebra/operator/sha384.rb +19 -2
  114. data/lib/sparql/algebra/operator/sha512.rb +19 -2
  115. data/lib/sparql/algebra/operator/slice.rb +27 -5
  116. data/lib/sparql/algebra/operator/str.rb +22 -2
  117. data/lib/sparql/algebra/operator/strafter.rb +26 -3
  118. data/lib/sparql/algebra/operator/strbefore.rb +26 -3
  119. data/lib/sparql/algebra/operator/strdt.rb +23 -2
  120. data/lib/sparql/algebra/operator/strends.rb +26 -4
  121. data/lib/sparql/algebra/operator/strlang.rb +25 -7
  122. data/lib/sparql/algebra/operator/strlen.rb +24 -3
  123. data/lib/sparql/algebra/operator/strstarts.rb +26 -3
  124. data/lib/sparql/algebra/operator/struuid.rb +30 -10
  125. data/lib/sparql/algebra/operator/subject.rb +33 -1
  126. data/lib/sparql/algebra/operator/substr.rb +24 -3
  127. data/lib/sparql/algebra/operator/subtract.rb +29 -3
  128. data/lib/sparql/algebra/operator/sum.rb +25 -7
  129. data/lib/sparql/algebra/operator/table.rb +76 -4
  130. data/lib/sparql/algebra/operator/timezone.rb +24 -6
  131. data/lib/sparql/algebra/operator/tz.rb +23 -6
  132. data/lib/sparql/algebra/operator/ucase.rb +24 -3
  133. data/lib/sparql/algebra/operator/union.rb +29 -6
  134. data/lib/sparql/algebra/operator/update.rb +46 -4
  135. data/lib/sparql/algebra/operator/using.rb +49 -2
  136. data/lib/sparql/algebra/operator/uuid.rb +28 -9
  137. data/lib/sparql/algebra/operator/with.rb +38 -4
  138. data/lib/sparql/algebra/operator/year.rb +24 -6
  139. data/lib/sparql/algebra/operator.rb +135 -14
  140. data/lib/sparql/algebra/sxp_extensions.rb +3 -3
  141. data/lib/sparql/algebra.rb +20 -3
  142. data/lib/sparql/grammar/meta.rb +1103 -907
  143. data/lib/sparql/grammar/parser11.rb +63 -56
  144. metadata +43 -29
  145. data/lib/sparql/algebra/operator/triple.rb +0 -27
@@ -3,8 +3,18 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL relational `=` (equal) comparison operator.
5
5
  #
6
- # @example
7
- # (= ?x ?y)
6
+ # [114] RelationalExpression ::= NumericExpression ('=' NumericExpression)?
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
10
+ # PREFIX : <http://example.org/things#>
11
+ # SELECT ?x
12
+ # WHERE { ?x :p ?v . FILTER ( ?v = 1 ) }
13
+ #
14
+ # @example SSE
15
+ # (prefix
16
+ # ((xsd: <http://www.w3.org/2001/XMLSchema#>) (: <http://example.org/things#>))
17
+ # (project (?x) (filter (= ?v 1) (bgp (triple ?x :p ?v)))))
8
18
  #
9
19
  # @see https://www.w3.org/TR/sparql11-query/#OperatorMapping
10
20
  # @see https://www.w3.org/TR/sparql11-query/#func-RDFterm-equal
@@ -26,7 +36,7 @@ module SPARQL; module Algebra
26
36
  # @raise [TypeError] if either operand is not an RDF term or operands are not comperable
27
37
  #
28
38
  # @see RDF::Term#==
29
- def apply(term1, term2)
39
+ def apply(term1, term2, **options)
30
40
  term1 = term1.dup.extend(RDF::TypeCheck)
31
41
  term2 = term2.dup.extend(RDF::TypeCheck)
32
42
  RDF::Literal(term1 == term2)
@@ -5,10 +5,21 @@ 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
- # @example
9
- # (prefix ((ex: <http://www.example.org/>))
10
- # (filter (exists (bgp (triple ?s ?p ex:o)))
11
- # (bgp (triple ?s ?p ?o))))
8
+ # [125] ExistsFunc ::= 'EXISTS' GroupGraphPattern
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example/>
12
+ # SELECT *
13
+ # WHERE {
14
+ # ?set a :Set .
15
+ # FILTER EXISTS { ?set :member 9 }
16
+ # }
17
+ #
18
+ # @example SSE
19
+ # (prefix ((: <http://example/>))
20
+ # (filter
21
+ # (exists (bgp (triple ?set :member 9)))
22
+ # (bgp (triple ?set a :Set))))
12
23
  #
13
24
  # @see https://www.w3.org/TR/sparql11-query/#func-filter-exists
14
25
  class Exists < Operator::Unary
@@ -32,6 +43,19 @@ module SPARQL; module Algebra
32
43
  depth: options[:depth].to_i + 1,
33
44
  **options).empty?
34
45
  end
46
+
47
+ ##
48
+ #
49
+ # Returns a partial SPARQL grammar for this operator.
50
+ #
51
+ # @param [Boolean] top_level (true)
52
+ # Treat this as a top-level, generating SELECT ... WHERE {}
53
+ # @return [String]
54
+ def to_sparql(top_level: true, **options)
55
+ "EXISTS {\n" +
56
+ operands.last.to_sparql(top_level: false, **options) +
57
+ "\n}"
58
+ end
35
59
  end # Exists
36
60
  end # Operator
37
61
  end; end # SPARQL::Algebra
@@ -5,8 +5,21 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Used for filters with more than one expression.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example/>))
8
+ # [72] ExpressionList ::= NIL | '(' Expression ( ',' Expression )* ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ #
13
+ # SELECT ?v ?w
14
+ # {
15
+ # FILTER (?v = 2)
16
+ # FILTER (?w = 3)
17
+ # ?s :p ?v .
18
+ # ?s :q ?w .
19
+ # }
20
+ #
21
+ # @example SSE
22
+ # (prefix ((: <http://example.org/>))
10
23
  # (project (?v ?w)
11
24
  # (filter (exprlist (= ?v 2) (= ?w 3))
12
25
  # (bgp
@@ -5,11 +5,52 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Extends a solution
7
7
  #
8
- # @example
9
- # (select (?z)
10
- # (project (?z)
11
- # (extend ((?z (+ ?o 10)))
12
- # (bgp (triple ?s <http://example/p> ?o)))))
8
+ # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # SELECT ?z
12
+ # {
13
+ # ?x <http://example.org/p> ?o
14
+ # BIND(?o+10 AS ?z)
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (project (?z)
19
+ # (extend ((?z (+ ?o 10)))
20
+ # (bgp (triple ?x <http://example.org/p> ?o))))
21
+ #
22
+ # @example SPARQL Grammar (cast as boolean)
23
+ # PREFIX : <http://example.org/>
24
+ # PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
25
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
26
+ # SELECT ?a ?v (xsd:boolean(?v) AS ?boolean)
27
+ # WHERE { ?a :p ?v . }
28
+ #
29
+ # @example SSE (cast as boolean)
30
+ # (prefix ((: <http://example.org/>)
31
+ # (rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
32
+ # (xsd: <http://www.w3.org/2001/XMLSchema#>))
33
+ # (project (?a ?v ?boolean)
34
+ # (extend ((?boolean (xsd:boolean ?v)))
35
+ # (bgp (triple ?a :p ?v)))))
36
+ #
37
+ # @example SPARQL Grammar (inner bind)
38
+ # PREFIX : <http://example.org/>
39
+ #
40
+ # SELECT ?z ?s1
41
+ # {
42
+ # ?s ?p ?o .
43
+ # BIND(?o+1 AS ?z)
44
+ # ?s1 ?p1 ?z
45
+ # }
46
+ #
47
+ # @example SSE (inner bind)
48
+ # (prefix ((: <http://example.org/>))
49
+ # (project (?z ?s1)
50
+ # (join
51
+ # (extend ((?z (+ ?o 1)))
52
+ # (bgp (triple ?s ?p ?o)))
53
+ # (bgp (triple ?s1 ?p1 ?z)))))
13
54
  #
14
55
  # @see https://www.w3.org/TR/sparql11-query/#evaluation
15
56
  class Extend < Operator::Binary
@@ -73,6 +114,23 @@ module SPARQL; module Algebra
73
114
  end
74
115
  super
75
116
  end
76
- end # Filter
117
+
118
+ ##
119
+ #
120
+ # Returns a partial SPARQL grammar for this operator.
121
+ #
122
+ # Extracts bindings.
123
+ #
124
+ # @return [String]
125
+ def to_sparql(**options)
126
+ extensions = operands.first.inject({}) do |memo, (as, expression)|
127
+ memo.merge(as => expression)
128
+ end
129
+
130
+ # Merge any inherited extensions from options
131
+ extensions = options.delete(:extensions).merge(extensions) if options.key?(:extensions)
132
+ operands.last.to_sparql(extensions: extensions, **options)
133
+ end
134
+ end # Extend
77
135
  end # Operator
78
136
  end; end # SPARQL::Algebra
@@ -3,11 +3,19 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `filter` operator.
5
5
  #
6
- # @example
7
- # (select (?v)
8
- # (project (?v)
9
- # (filter (= ?v 2)
10
- # (bgp (triple ?s <http://example/p> ?v)))))
6
+ # [68] Filter ::= 'FILTER' Constraint
7
+ #
8
+ # @example SPARQL Grammar
9
+ # SELECT ?v
10
+ # {
11
+ # ?s <http://example/p> ?v
12
+ # FILTER(?v = 2)
13
+ # }
14
+ #
15
+ # @example SSE
16
+ # (project (?v)
17
+ # (filter (= ?v 2)
18
+ # (bgp (triple ?s <http://example/p> ?v))))
11
19
  #
12
20
  # @see https://www.w3.org/TR/sparql11-query/#evaluation
13
21
  class Filter < Operator::Binary
@@ -69,6 +77,20 @@ module SPARQL; module Algebra
69
77
  end
70
78
  self
71
79
  end
80
+
81
+ ##
82
+ #
83
+ # Returns a partial SPARQL grammar for this operator.
84
+ #
85
+ # Provides filters to descendant query.
86
+ #
87
+ # If filter operation is an Exprlist, then separate into multiple filter ops.
88
+ #
89
+ # @return [String]
90
+ def to_sparql(**options)
91
+ filter_ops = operands.first.is_a?(Operator::Exprlist) ? operands.first.operands : [operands.first]
92
+ str = operands.last.to_sparql(filter_ops: filter_ops, **options)
93
+ end
72
94
  end # Filter
73
95
  end # Operator
74
96
  end; end # SPARQL::Algebra
@@ -3,8 +3,22 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL logical `floor` operator.
5
5
  #
6
- # @example
7
- # (floor ?x)
6
+ # [121] BuiltInCall ::= ... 'FLOOR' '(' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # SELECT ?s ?num (FLOOR(?num) AS ?floor) 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 ?floor)
20
+ # (extend ((?floor (floor ?num)))
21
+ # (bgp (triple ?s :num ?num)))))
8
22
  #
9
23
  # @see https://www.w3.org/TR/sparql11-query/#func-floor
10
24
  # @see https://www.w3.org/TR/xpath-functions/#func-floor
@@ -24,12 +38,21 @@ module SPARQL; module Algebra
24
38
  # the operand
25
39
  # @return [RDF::Literal] literal of same type
26
40
  # @raise [TypeError] if the operand is not a numeric value
27
- def apply(operand)
41
+ def apply(operand, **options)
28
42
  case operand
29
43
  when RDF::Literal::Numeric then operand.floor
30
44
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
31
45
  end
32
46
  end
47
+
48
+ ##
49
+ #
50
+ # Returns a partial SPARQL grammar for this operator.
51
+ #
52
+ # @return [String]
53
+ def to_sparql(**options)
54
+ "FLOOR(#{operands.to_sparql(**options)})"
55
+ end
33
56
  end # Floor
34
57
  end # Operator
35
58
  end; end # SPARQL::Algebra
@@ -0,0 +1,64 @@
1
+
2
+ module SPARQL; module Algebra
3
+ class Operator
4
+ ##
5
+ # The SPARQL `function_call` operator.
6
+ #
7
+ # [70] FunctionCall ::= iri ArgList
8
+ #
9
+ # @example SPARQL Grammar
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # SELECT *
12
+ # WHERE { ?s ?p ?o . FILTER xsd:integer(?o) }
13
+ #
14
+ # @example SSE
15
+ # (prefix
16
+ # ((xsd: <http://www.w3.org/2001/XMLSchema#>))
17
+ # (filter (xsd:integer ?o)
18
+ # (bgp (triple ?s ?p ?o))))
19
+ #
20
+ # @see https://www.w3.org/TR/sparql11-query/#funcex-regex
21
+ # @see https://www.w3.org/TR/xpath-functions/#func-matches
22
+ class FunctionCall < Operator
23
+ include Evaluatable
24
+
25
+ NAME = :function_call
26
+
27
+ ##
28
+ # Invokes the function with the passed arguments.
29
+ #
30
+ # @param [RDF::IRI] iri
31
+ # Identifies the function
32
+ # @param [Array<RDF::Term>] args
33
+ # @return [RDF::Term]
34
+ def apply(iri, *args, **options)
35
+ args = RDF.nil == args.last ? args[0..-2] : args
36
+ SPARQL::Algebra::Expression.extension(iri, *args, **options)
37
+ end
38
+
39
+ ##
40
+ # Returns the SPARQL S-Expression (SSE) representation of this expression.
41
+ #
42
+ # Remove the optional argument.
43
+ #
44
+ # @return [Array] `self`
45
+ # @see https://openjena.org/wiki/SSE
46
+ def to_sxp_bin
47
+ @operands.map(&:to_sxp_bin)
48
+ end
49
+
50
+ ##
51
+ #
52
+ # Returns a partial SPARQL grammar for this operator.
53
+ #
54
+ # @return [String]
55
+ def to_sparql(**options)
56
+ iri, args = operands
57
+ iri.to_sparql(**options) +
58
+ '(' +
59
+ args.to_sparql(delimiter: ', ', **options) +
60
+ ')'
61
+ end
62
+ end # FunctionCall
63
+ end # Operator
64
+ end; end # SPARQL::Algebra
@@ -5,15 +5,63 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # This is a wrapper to add a `graph_name` to the query, or an array of statements.
7
7
  #
8
- # @example of a query
8
+ # [58] GraphGraphPattern ::= 'GRAPH' VarOrIri GroupGraphPattern
9
+ #
10
+ # @example SPARQL Grammar (query)
11
+ # PREFIX : <http://example/>
12
+ # SELECT * {
13
+ # GRAPH ?g { ?s ?p ?o }
14
+ # }
15
+ #
16
+ # @example SSE
9
17
  # (prefix ((: <http://example/>))
10
- # (graph ?g
11
- # (bgp (triple ?s ?p ?o))))
18
+ # (graph ?g
19
+ # (bgp (triple ?s ?p ?o))))
20
+ #
21
+ # @example SPARQL Grammar (named set of statements)
22
+ # PREFIX : <http://example/>
23
+ # SELECT * {
24
+ # GRAPH :g { :s :p :o }
25
+ # }
12
26
  #
13
- # @example named set of statements
27
+ # @example SSE (named set of statements)
14
28
  # (prefix ((: <http://example/>))
15
- # (graph :g
16
- # ((triple :s :p :o))))
29
+ # (graph :g
30
+ # (bgp (triple :s :p :o))))
31
+ #
32
+ # @example SPARQL Grammar (syntax-graph-05.rq)
33
+ # PREFIX : <http://example.org/>
34
+ # SELECT *
35
+ # WHERE
36
+ # {
37
+ # :x :p :z
38
+ # GRAPH ?g { :x :b ?a . GRAPH ?g2 { :x :p ?x } }
39
+ # }
40
+ #
41
+ # @example SSE (syntax-graph-05.rq)
42
+ # (prefix ((: <http://example.org/>))
43
+ # (join
44
+ # (bgp (triple :x :p :z))
45
+ # (graph ?g
46
+ # (join
47
+ # (bgp (triple :x :b ?a))
48
+ # (graph ?g2
49
+ # (bgp (triple :x :p ?x)))))))
50
+ #
51
+ # @example SPARQL Grammar (pp06.rq)
52
+ # prefix ex: <http://www.example.org/schema#>
53
+ # prefix in: <http://www.example.org/instance#>
54
+ #
55
+ # select ?x where {
56
+ # graph ?g {in:a ex:p1/ex:p2 ?x}
57
+ # }
58
+ #
59
+ # @example SSE (syntax-graph-05.rq)
60
+ # (prefix ((ex: <http://www.example.org/schema#>)
61
+ # (in: <http://www.example.org/instance#>))
62
+ # (project (?x)
63
+ # (graph ?g
64
+ # (path in:a (seq ex:p1 ex:p2) ?x))))
17
65
  #
18
66
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
19
67
  class Graph < Operator::Binary
@@ -76,6 +124,21 @@ module SPARQL; module Algebra
76
124
  def rewrite(&block)
77
125
  self
78
126
  end
127
+
128
+ ##
129
+ #
130
+ # Returns a partial SPARQL grammar for this operator.
131
+ #
132
+ # @param [Boolean] top_level (true)
133
+ # Treat this as a top-level, generating SELECT ... WHERE {}
134
+ # @return [String]
135
+ def to_sparql(top_level: true, **options)
136
+ query = operands.last.to_sparql(top_level: false, **options)
137
+ # Paths don't automatically get braces.
138
+ query = "{\n#{query}\n}" unless query.start_with?('{')
139
+ str = "GRAPH #{operands.first.to_sparql(**options)} " + query
140
+ top_level ? Operator.to_sparql(str, **options) : str
141
+ end
79
142
  end # Graph
80
143
  end # Operator
81
144
  end; end # SPARQL::Algebra
@@ -3,8 +3,18 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL relational `>` (greater than) comparison operator.
5
5
  #
6
- # @example
7
- # (> ?x ?y)
6
+ # [114] RelationalExpression ::= NumericExpression ('>' NumericExpression)?
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
10
+ # PREFIX : <http://example.org/things#>
11
+ # SELECT ?x
12
+ # WHERE { ?x :p ?v . FILTER ( ?v > 1 ) }
13
+ #
14
+ # @example SSE
15
+ # (prefix
16
+ # ((xsd: <http://www.w3.org/2001/XMLSchema#>) (: <http://example.org/things#>))
17
+ # (project (?x) (filter (> ?v 1) (bgp (triple ?x :p ?v)))))
8
18
  #
9
19
  # @see https://www.w3.org/TR/sparql11-query/#OperatorMapping
10
20
  # @see https://www.w3.org/TR/xpath-functions/#func-compare
@@ -24,8 +34,8 @@ module SPARQL; module Algebra
24
34
  # a literal
25
35
  # @return [RDF::Literal::Boolean] `true` or `false`
26
36
  # @raise [TypeError] if either operand is not a literal
27
- def apply(left, right)
28
- super
37
+ def apply(left, right, **options)
38
+ RDF::Literal(super == RDF::Literal(1))
29
39
  end
30
40
  end # GreaterThan
31
41
  end # Operator
@@ -4,8 +4,18 @@ module SPARQL; module Algebra
4
4
  # The SPARQL relational `>=` (greater than or equal) comparison
5
5
  # operator.
6
6
  #
7
- # @example
8
- # (>= ?x ?y)
7
+ # [114] RelationalExpression ::= NumericExpression ('>=' NumericExpression)?
8
+ #
9
+ # @example SPARQL Grammar
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # PREFIX : <http://example.org/things#>
12
+ # SELECT ?x
13
+ # WHERE { ?x :p ?v . FILTER ( ?v >= 1 ) }
14
+ #
15
+ # @example SSE
16
+ # (prefix
17
+ # ((xsd: <http://www.w3.org/2001/XMLSchema#>) (: <http://example.org/things#>))
18
+ # (project (?x) (filter (>= ?v 1) (bgp (triple ?x :p ?v)))))
9
19
  #
10
20
  # @see https://www.w3.org/TR/sparql11-query/#OperatorMapping
11
21
  # @see https://www.w3.org/TR/xpath-functions/#func-compare
@@ -25,8 +35,8 @@ module SPARQL; module Algebra
25
35
  # a literal
26
36
  # @return [RDF::Literal::Boolean] `true` or `false`
27
37
  # @raise [TypeError] if either operand is not a literal
28
- def apply(left, right)
29
- super
38
+ def apply(left, right, **options)
39
+ RDF::Literal(super >= RDF::Literal(0))
30
40
  end
31
41
  end # GreaterThanOrEqual
32
42
  end # Operator
@@ -8,14 +8,53 @@ module SPARQL; module Algebra
8
8
  # query to be grouped. If three operands are provided,
9
9
  # the second is an array of temporary bindings.
10
10
  #
11
- # @example
12
- # (prefix ((: <http://example/>))
13
- # (project (?w ?S)
14
- # (extend ((?S ??.0))
15
- # (group (?w) ((??.0 (sample ?v)))
16
- # (leftjoin
17
- # (bgp (triple ?s :p ?v))
18
- # (bgp (triple ?s :q ?w)))))))
11
+ # [19] GroupClause ::= 'GROUP' 'BY' GroupCondition+
12
+ #
13
+ # @example SPARQL Grammar
14
+ # PREFIX : <http://www.example.org>
15
+ #
16
+ # SELECT ?P (COUNT(?O) AS ?C)
17
+ # WHERE { ?S ?P ?O }
18
+ # GROUP BY ?P
19
+ #
20
+ # @example SSE
21
+ # (prefix
22
+ # ((: <http://www.example.org>))
23
+ # (project (?P ?C)
24
+ # (extend ((?C ??.0))
25
+ # (group (?P) ((??.0 (count ?O)))
26
+ # (bgp (triple ?S ?P ?O))))))
27
+ #
28
+ # @example SPARQL Grammar (HAVING aggregate)
29
+ # PREFIX : <http://www.example.org/>
30
+ # SELECT ?s (AVG(?o) AS ?avg)
31
+ # WHERE { ?s ?p ?o }
32
+ # GROUP BY ?s
33
+ # HAVING (AVG(?o) <= 2.0)
34
+ #
35
+ # @example SSE (HAVING aggregate)
36
+ # (prefix ((: <http://www.example.org/>))
37
+ # (project (?s ?avg)
38
+ # (filter (<= ??.0 2.0)
39
+ # (extend ((?avg ??.0))
40
+ # (group (?s) ((??.0 (avg ?o)))
41
+ # (bgp (triple ?s ?p ?o)))))) )
42
+ #
43
+ # @example SPARQL Grammar (non-triveal filters)
44
+ # PREFIX : <http://example.com/data/#>
45
+ # SELECT ?g (AVG(?p) AS ?avg) ((MIN(?p) + MAX(?p)) / 2 AS ?c)
46
+ # WHERE { ?g :p ?p . }
47
+ # GROUP BY ?g
48
+ #
49
+ # @example SSE (non-triveal filters)
50
+ # (prefix ((: <http://example.com/data/#>))
51
+ # (project (?g ?avg ?c)
52
+ # (extend ((?avg ??.0) (?c (/ (+ ??.1 ??.2) 2)))
53
+ # (group (?g)
54
+ # ((??.0 (avg ?p))
55
+ # (??.1 (min ?p))
56
+ # (??.2 (max ?p)))
57
+ # (bgp (triple ?g :p ?p)))) ))
19
58
  #
20
59
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
21
60
  class Group < Operator
@@ -122,6 +161,64 @@ module SPARQL; module Algebra
122
161
  end
123
162
  super
124
163
  end
164
+
165
+ ##
166
+ #
167
+ # Returns a partial SPARQL grammar for this operator.
168
+ #
169
+ # @param [Hash{Symbol => Operator}] extensions
170
+ # Variable bindings
171
+ # @param [Array<Operator>] filter_ops ([])
172
+ # Filter Operations
173
+ # @return [String]
174
+ def to_sparql(extensions: {}, filter_ops: [], **options)
175
+ having_ops = []
176
+ if operands.length > 2
177
+ temp_bindings = operands[1].inject({}) {|memo, (var, op)| memo.merge(var => op)}
178
+ # Replace extensions from temporary bindings
179
+ temp_bindings.each do |var, op|
180
+ # Update extensions using a temporarily bound variable with its binding
181
+ extensions = extensions.inject({}) do |memo, (ext_var, ext_op)|
182
+ if ext_op.is_a?(Operator)
183
+ # Try to recursivley replace variable within operator
184
+ new_op = ext_op.deep_dup.rewrite do |operand|
185
+ if operand.is_a?(Variable) && operand.to_sym == var.to_sym
186
+ op.dup
187
+ else
188
+ operand
189
+ end
190
+ end
191
+ memo.merge(ext_var => new_op)
192
+ elsif ext_op.is_a?(Variable) && ext_op.to_sym == var.to_sym
193
+ memo.merge(ext_var => op)
194
+ else
195
+ # Doesn't match this variable, so don't change
196
+ memo.merge(ext_var => ext_op)
197
+ end
198
+ end
199
+
200
+ # Filter ops using temporary bindinds are used for HAVING clauses
201
+ filter_ops.each do |fop|
202
+ having_ops << fop if fop.descendants.include?(var) && !having_ops.include?(fop)
203
+ end
204
+ end
205
+
206
+ # If used in a HAVING clause, it's not also a filter
207
+ filter_ops -= having_ops
208
+
209
+ # Replace each operand in having using var with it's corresponding operation
210
+ having_ops = having_ops.map do |op|
211
+ op.dup.rewrite do |operand|
212
+ # Rewrite based on temporary bindings
213
+ temp_bindings.fetch(operand, operand)
214
+ end
215
+ end
216
+ end
217
+ operands.last.to_sparql(extensions: extensions,
218
+ group_ops: operands.first,
219
+ having_ops: having_ops,
220
+ **options)
221
+ end
125
222
  end # Group
126
223
  end # Operator
127
224
  end; end # SPARQL::Algebra