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 Property Path `path*` (ZeroOrMorePath) operator.
5
5
  #
6
- # @example
7
- # (path* :p)
6
+ # [91] PathElt ::= PathPrimary PathMod?
7
+ # [93] PathMod ::= '*' | '?' | '+'
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_ZeroOrMorePath
10
20
  class PathStar < Operator::Unary
@@ -37,6 +47,14 @@ module SPARQL; module Algebra
37
47
  query = PathOpt.new(PathPlus.new(*operands))
38
48
  query.execute(queryable, depth: options[:depth].to_i + 1, **options, &block)
39
49
  end
50
+ ##
51
+ #
52
+ # Returns a partial SPARQL grammar for this operator.
53
+ #
54
+ # @return [String]
55
+ def to_sparql(**options)
56
+ "(#{operands.first.to_sparql(**options)})*"
57
+ end
40
58
  end # PathStar
41
59
  end # Operator
42
60
  end; end # SPARQL::Algebra
@@ -3,9 +3,39 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL numeric binary/unary `+` operator.
5
5
  #
6
- # @example
7
- # (+ ?x ?y)
8
- # (plus ?x ?y)
6
+ # [118] UnaryExpression ::= ... | '+' PrimaryExpression
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?s WHERE {
11
+ # ?s :p ?o .
12
+ # FILTER(-?o = +3) .
13
+ # }
14
+ #
15
+ # @example SSE
16
+ # (prefix ((: <http://example.org/>))
17
+ # (project (?s)
18
+ # (filter (= (- ?o) +3)
19
+ # (bgp (triple ?s :p ?o)))))
20
+ #
21
+ # [116] AdditiveExpression ::= MultiplicativeExpression ( '+' MultiplicativeExpression )?
22
+ #
23
+ # @example SPARQL Grammar
24
+ # PREFIX : <http://example.org/>
25
+ # SELECT ?s WHERE {
26
+ # ?s :p ?o .
27
+ # ?s2 :p ?o2 .
28
+ # FILTER(?o + ?o2 = 3) .
29
+ # }
30
+ #
31
+ # @example SSE
32
+ # (prefix
33
+ # ((: <http://example.org/>))
34
+ # (project (?s)
35
+ # (filter (= (+ ?o ?o2) 3)
36
+ # (bgp
37
+ # (triple ?s :p ?o)
38
+ # (triple ?s2 :p ?o2)))))
9
39
  #
10
40
  # @see https://www.w3.org/TR/xpath-functions/#func-numeric-unary-plus
11
41
  # @see https://www.w3.org/TR/xpath-functions/#func-numeric-add
@@ -23,7 +53,7 @@ module SPARQL; module Algebra
23
53
  # a numeric literal
24
54
  # @return [RDF::Literal::Numeric]
25
55
  # @raise [TypeError] if either operand is not a numeric literal
26
- def apply(left, right = nil)
56
+ def apply(left, right = nil, **options)
27
57
  case
28
58
  when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
29
59
  left + right
@@ -32,6 +62,15 @@ module SPARQL; module Algebra
32
62
  else raise TypeError, "expected two RDF::Literal::Numeric operands, but got #{left.inspect} and #{right.inspect}"
33
63
  end
34
64
  end
65
+
66
+ ##
67
+ #
68
+ # Returns a partial SPARQL grammar for this operator.
69
+ #
70
+ # @return [String]
71
+ def to_sparql(**options)
72
+ "(#{operands.first.to_sparql(**options)} + #{operands.last.to_sparql(**options)})"
73
+ end
35
74
  end # Plus
36
75
  end # Operator
37
76
  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 predicate of this triple. Passing anything other than an RDF-star triple is an error.
7
7
  #
8
+ # [121] BuiltInCall ::= ... | 'PREDICATE' '(' 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#predicate
9
32
  class Predicate < Operator::Unary
10
33
  include Evaluatable
@@ -18,10 +41,19 @@ module SPARQL; module Algebra
18
41
  # the operand
19
42
  # @return [RDF::Literal]
20
43
  # @raise [TypeError] if the operand is not a statement
21
- def apply(operand)
44
+ def apply(operand, **options)
22
45
  raise TypeError, "expected an RDF::Statement, but got #{operand.inspect}" unless operand.is_a?(RDF::Statement)
23
46
  operand.predicate
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
+ "PREDICATE(" + operands.last.to_sparql(**options) + ")"
56
+ end
25
57
  end # Predicate
26
58
  end # Operator
27
59
  end; end # SPARQL::Algebra
@@ -3,10 +3,15 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `prefix` operator.
5
5
  #
6
- # @example
6
+ # [6] PrefixDecl ::= 'PREFIX' PNAME_NS IRIREF
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example/>
10
+ # SELECT * { :s :p :o }
11
+ #
12
+ # @example SSE
7
13
  # (prefix ((: <http://example/>))
8
- # (graph ?g
9
- # (bgp (triple ?s ?p ?o))))
14
+ # (bgp (triple :s :p :o)))
10
15
  #
11
16
  # @see https://www.w3.org/TR/sparql11-query/#QSynIRI
12
17
  class Prefix < Binary
@@ -65,6 +70,22 @@ module SPARQL; module Algebra
65
70
  def query_yields_statements?
66
71
  operands.last.query_yields_statements?
67
72
  end
73
+
74
+ ##
75
+ #
76
+ # Returns a partial SPARQL grammar for this term.
77
+ #
78
+ # @return [String]
79
+ def to_sparql(**options)
80
+ prefixes = {}
81
+ str = operands.first.map do |(pfx, sfx)|
82
+ pfx = pfx.to_s.chomp(':').to_sym
83
+ prefixes[pfx] = sfx
84
+ "PREFIX #{pfx}: #{sfx.to_sparql}\n"
85
+ end.join("")
86
+
87
+ str << operands.last.to_sparql(prefixes: prefixes, **options)
88
+ end
68
89
  end # Prefix
69
90
  end # Operator
70
91
  end; end # SPARQL::Algebra
@@ -3,11 +3,53 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `project` operator.
5
5
  #
6
- # @example
7
- # (select (?v)
8
- # (project (?v)
9
- # (filter (= ?v 2)
10
- # (bgp (triple ?s <http://example/p> ?v)))))
6
+ # [9] SelectClause ::= 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
7
+ #
8
+ # ## Basic Projection
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example/>
12
+ # SELECT ?v {
13
+ # ?s :p ?v .
14
+ # FILTER (?v = 2)
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (prefix ((: <http://example/>))
19
+ # (project (?v)
20
+ # (filter (= ?v 2)
21
+ # (bgp (triple ?s :p ?v)))))
22
+ #
23
+ # @example SPARQL Grammar (Sub select)
24
+ # SELECT (1 AS ?X ) {
25
+ # SELECT (2 AS ?Y ) {}
26
+ # }
27
+ #
28
+ # @example SSE (Sub select)
29
+ # (project (?X)
30
+ # (extend ((?X 1))
31
+ # (project (?Y)
32
+ # (extend ((?Y 2))
33
+ # (bgp)))))
34
+ #
35
+ # @example SPARQL Grammar (filter projection)
36
+ # PREFIX : <http://www.example.org/>
37
+ # ASK {
38
+ # {SELECT (GROUP_CONCAT(?o) AS ?g) WHERE {
39
+ # :a :p1 ?o
40
+ # }}
41
+ # FILTER(?g = "1 22" || ?g = "22 1")
42
+ # }
43
+ #
44
+ # @example SSE (filter projection)
45
+ # (prefix ((: <http://www.example.org/>))
46
+ # (ask
47
+ # (filter
48
+ # (|| (= ?g "1 22") (= ?g "22 1"))
49
+ # (project (?g)
50
+ # (extend ((?g ??.0))
51
+ # (group () ((??.0 (group_concat ?o)))
52
+ # (bgp (triple :a :p1 ?o)))))) ))
11
53
  #
12
54
  # @see https://www.w3.org/TR/sparql11-query/#modProjection
13
55
  class Project < Operator::Binary
@@ -36,6 +78,28 @@ module SPARQL; module Algebra
36
78
  @solutions.each(&block) if block_given?
37
79
  @solutions
38
80
  end
81
+
82
+ ##
83
+ #
84
+ # Returns a partial SPARQL grammar for this operator.
85
+ #
86
+ # Extracts projections
87
+ #
88
+ # If there are already extensions or filters, then this is a sub-select.
89
+ #
90
+ # @return [String]
91
+ def to_sparql(**options)
92
+ vars = operands[0].empty? ? [:*] : operands[0]
93
+ if options[:extensions] || options[:filter_ops] || options[:project]
94
+ # Any of these options indicates we're in a sub-select
95
+ opts = options.dup.delete_if {|k,v| %I{extensions filter_ops project}.include?(k)}
96
+ content = operands.last.to_sparql(project: vars, **opts)
97
+ content = "{#{content}}" unless content.start_with?('{') && content.end_with?('}')
98
+ Operator.to_sparql(content, **options)
99
+ else
100
+ operands.last.to_sparql(project: vars, **options)
101
+ end
102
+ end
39
103
  end # Project
40
104
  end # Operator
41
105
  end; end # SPARQL::Algebra
@@ -5,8 +5,25 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Returns a pseudo-random number between 0 (inclusive) and 1.0e0 (exclusive). Different numbers can be produced every time this function is invoked. Numbers should be produced with approximately equal probability.
7
7
  #
8
- # @example
9
- # (rand)
8
+ # [121] BuiltInCall ::= ... | 'RAND' NIL
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
12
+ # ASK {
13
+ # BIND(RAND() AS ?r)
14
+ # FILTER(DATATYPE(?r) = xsd:double && ?r >= 0.0 && ?r < 1.0)
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (prefix
19
+ # ((xsd: <http://www.w3.org/2001/XMLSchema#>))
20
+ # (ask
21
+ # (filter
22
+ # (&&
23
+ # (&& (= (datatype ?r) xsd:double) (>= ?r 0.0))
24
+ # (< ?r 1.0))
25
+ # (extend ((?r (rand)))
26
+ # (bgp)))))
10
27
  #
11
28
  # @see https://www.w3.org/TR/sparql11-query/#idp2130040
12
29
  class Rand < Operator::Nullary
@@ -18,9 +35,20 @@ module SPARQL; module Algebra
18
35
  # Returns a pseudo-random number between 0 (inclusive) and 1.0e0 (exclusive). Different numbers can be produced every time this function is invoked. Numbers should be produced with approximately equal probability.
19
36
  #
20
37
  # @return [RDF::Literal::Double] random value
21
- def apply
38
+ def apply(**options)
22
39
  RDF::Literal::Double.new(Random.rand)
23
40
  end
41
+
42
+ ##
43
+ #
44
+ # Returns a partial SPARQL grammar for this operator.
45
+ #
46
+ # Extracts projections
47
+ #
48
+ # @return [String]
49
+ def to_sparql(**options)
50
+ "RAND()"
51
+ end
24
52
  end # Rand
25
53
  end # Operator
26
54
  end; end # SPARQL::Algebra
@@ -3,9 +3,17 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `reduced` operator.
5
5
  #
6
- # @example
7
- # (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
8
- # (: <http://example/>))
6
+ # [9] SelectClause ::= 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # SELECT REDUCED ?v
12
+ # WHERE { ?x ?p ?v }
13
+ #
14
+ # @example SSE
15
+ # (prefix ((: <http://example.org/>)
16
+ # (xsd: <http://www.w3.org/2001/XMLSchema#>))
9
17
  # (reduced
10
18
  # (project (?v)
11
19
  # (bgp (triple ?x ?p ?v)))))
@@ -37,6 +45,15 @@ module SPARQL; module Algebra
37
45
  @solutions.each(&block) if block_given?
38
46
  @solutions
39
47
  end
48
+
49
+ ##
50
+ #
51
+ # Returns a partial SPARQL grammar for this operator.
52
+ #
53
+ # @return [String]
54
+ def to_sparql(**options)
55
+ operands.first.to_sparql(reduced: true, **options)
56
+ end
40
57
  end # Reduced
41
58
  end # Operator
42
59
  end; end # SPARQL::Algebra
@@ -3,33 +3,31 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `regex` operator.
5
5
  #
6
- # @example
6
+ # [122] RegexExpression ::= 'REGEX' '(' Expression ',' Expression ( ',' Expression )? ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX ex: <http://example.com/#>
10
+ # PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
11
+ # SELECT ?val
12
+ # WHERE {
13
+ # ex:foo rdf:value ?val .
14
+ # FILTER regex(?val, "GHI")
15
+ # }
16
+ #
17
+ # @example SSE
7
18
  # (prefix ((ex: <http://example.com/#>)
8
19
  # (rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>))
9
- # (project (?val)
10
- # (filter (regex ?val "GHI")
11
- # (bgp (triple ex:foo rdf:value ?val)))))
20
+ # (project (?val)
21
+ # (filter (regex ?val "GHI")
22
+ # (bgp (triple ex:foo rdf:value ?val)))))
12
23
  #
13
24
  # @see https://www.w3.org/TR/sparql11-query/#funcex-regex
14
25
  # @see https://www.w3.org/TR/xpath-functions/#func-matches
15
- class Regex < Operator::Ternary
26
+ class Regex < Operator
16
27
  include Evaluatable
17
28
 
18
29
  NAME = :regex
19
30
 
20
- ##
21
- # Initializes a new operator instance.
22
- #
23
- # @param [RDF::Term] text
24
- # @param [RDF::Term] pattern
25
- # @param [RDF::Term] flags
26
- # @param [Hash{Symbol => Object}] options
27
- # any additional options (see {Operator#initialize})
28
- # @raise [TypeError] if any operand is invalid
29
- def initialize(text, pattern, flags = RDF::Literal(''), **options)
30
- super
31
- end
32
-
33
31
  ##
34
32
  # Matches `text` against a regular expression `pattern`.
35
33
  #
@@ -42,7 +40,7 @@ module SPARQL; module Algebra
42
40
  # @return [RDF::Literal::Boolean] `true` or `false`
43
41
  # @raise [TypeError] if any operand is unbound
44
42
  # @raise [TypeError] if any operand is not a simple literal
45
- def apply(text, pattern, flags = RDF::Literal(''))
43
+ def apply(text, pattern, flags = RDF::Literal(''), **options)
46
44
  # @see https://www.w3.org/TR/xpath-functions/#regex-syntax
47
45
  raise TypeError, "expected a plain RDF::Literal, but got #{text.inspect}" unless text.is_a?(RDF::Literal) && text.plain?
48
46
  text = text.to_s
@@ -65,6 +63,16 @@ module SPARQL; module Algebra
65
63
  options |= Regexp::EXTENDED if flags.include?(?x)
66
64
  RDF::Literal(Regexp.new(pattern, options) === text)
67
65
  end
66
+
67
+ ##
68
+ #
69
+ # Returns a partial SPARQL grammar for this operator.
70
+ #
71
+ # @return [String]
72
+ def to_sparql(**options)
73
+ ops = operands.last.to_s.empty? ? operands[0..-2] : operands
74
+ "regex(" + ops.to_sparql(delimiter: ', ', **options) + ")"
75
+ end
68
76
  end # Regex
69
77
  end # Operator
70
78
  end; end # SPARQL::Algebra
@@ -3,12 +3,22 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `replace` operator.
5
5
  #
6
- # @example
7
- # (prefix ((: <http://example.org/>)
8
- # (xsd: <http://www.w3.org/2001/XMLSchema#>))
9
- # (project (?s ?new)
10
- # (extend ((?new (replace ?str "[^a-z0-9]" "-")))
11
- # (bgp (triple ?s :str ?str)))))
6
+ # [124] StrReplaceExpression ::= 'REPLACE' '(' Expression ',' Expression ',' Expression ( ',' Expression )? ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
11
+ # SELECT ?s (REPLACE(?str,"[^a-z0-9]", "-") AS ?new)
12
+ # WHERE {
13
+ # ?s :str ?str
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix ((: <http://example.org/>)
18
+ # (xsd: <http://www.w3.org/2001/XMLSchema#>))
19
+ # (project (?s ?new)
20
+ # (extend ((?new (replace ?str "[^a-z0-9]" "-")))
21
+ # (bgp (triple ?s :str ?str)))))
12
22
  #
13
23
  # @see https://www.w3.org/TR/sparql11-query/#funcex-replace
14
24
  # @see https://www.w3.org/TR/xpath-functions/#func-replace
@@ -42,7 +52,7 @@ module SPARQL; module Algebra
42
52
  # @return [RDF::Literal]
43
53
  # @raise [TypeError] if any operand is unbound
44
54
  # @raise [TypeError] if any operand is not a plain literal
45
- def apply(text, pattern, replacement, flags = RDF::Literal(''))
55
+ def apply(text, pattern, replacement, flags = RDF::Literal(''), **options)
46
56
  raise TypeError, "expected a plain RDF::Literal, but got #{text.inspect}" unless text.literal? && text.plain?
47
57
  # TODO: validate text syntax
48
58
 
@@ -76,6 +86,16 @@ module SPARQL; module Algebra
76
86
  def to_sxp_bin
77
87
  [NAME] + operands.reject {|o| o.to_s == ""}
78
88
  end
89
+
90
+ ##
91
+ #
92
+ # Returns a partial SPARQL grammar for this operator.
93
+ #
94
+ # @return [String]
95
+ def to_sparql(**options)
96
+ ops = operands.last.to_s.empty? ? operands[0..-2] : operands
97
+ "REPLACE(" + ops.to_sparql(delimiter: ', ', **options) + ")"
98
+ end
79
99
  end # Replace
80
100
  end # Operator
81
101
  end; end # SPARQL::Algebra
@@ -3,8 +3,28 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL Property Path `reverse` (NegatedPropertySet) operator.
5
5
  #
6
- # @example
7
- # (reverse :p)
6
+ # [92] PathEltOrInverse ::= PathElt | '^' PathElt
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX ex: <http://www.example.org/schema#>
10
+ # PREFIX in: <http://www.example.org/instance#>
11
+ # ASK { in:b ^ex:p in:a }
12
+ #
13
+ # @example SSE
14
+ # (prefix ((ex: <http://www.example.org/schema#>)
15
+ # (in: <http://www.example.org/instance#>))
16
+ # (ask (path in:b (reverse ex:p) in:a)))
17
+ #
18
+ # @example SPARQL Grammar
19
+ # prefix ex: <http://www.example.org/schema#>
20
+ # prefix in: <http://www.example.org/instance#>
21
+ #
22
+ # select * where { in:c ^(ex:p1/ex:p2) ?x }
23
+ #
24
+ # @example SSE
25
+ # (prefix ((ex: <http://www.example.org/schema#>)
26
+ # (in: <http://www.example.org/instance#>))
27
+ # (path in:c (reverse (seq ex:p1 ex:p2)) ?x))
8
28
  #
9
29
  # @see https://www.w3.org/TR/sparql11-query/#defn_evalPP_inverse
10
30
  class Reverse < Operator::Unary
@@ -49,6 +69,15 @@ module SPARQL; module Algebra
49
69
  ), &block)
50
70
 
51
71
  end
72
+
73
+ ##
74
+ #
75
+ # Returns a partial SPARQL grammar for this operator.
76
+ #
77
+ # @return [String]
78
+ def to_sparql(**options)
79
+ "^(" + operands.first.to_sparql(**options) + ')'
80
+ end
52
81
  end # Reverse
53
82
  end # Operator
54
83
  end; end # SPARQL::Algebra
@@ -5,8 +5,22 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Returns the number with no fractional part that is closest to the argument. If there are two such numbers, then the one that is closest to positive infinity is returned. An error is raised if `arg` is not a numeric value.
7
7
  #
8
- # @example
9
- # (round ?x)
8
+ # [121] BuiltInCall ::= ... 'ROUND' '(' Expression ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
13
+ # SELECT ?s ?num (ROUND(?num) AS ?round) WHERE {
14
+ # ?s :num ?num
15
+ # }
16
+ #
17
+ # @example SSE
18
+ # (prefix
19
+ # ((: <http://example.org/>)
20
+ # (xsd: <http://www.w3.org/2001/XMLSchema#>))
21
+ # (project (?s ?num ?round)
22
+ # (extend ((?round (round ?num)))
23
+ # (bgp (triple ?s :num ?num)))))
10
24
  #
11
25
  # @see https://www.w3.org/TR/sparql11-query/#func-round
12
26
  # @see https://www.w3.org/TR/xpath-functions/#func-round
@@ -22,12 +36,21 @@ module SPARQL; module Algebra
22
36
  # the operand
23
37
  # @return [RDF::Literal] literal of same type
24
38
  # @raise [TypeError] if the operand is not a numeric value
25
- def apply(operand)
39
+ def apply(operand, **options)
26
40
  case operand
27
41
  when RDF::Literal::Numeric then operand.round
28
42
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
29
43
  end
30
44
  end
31
45
  end # Round
46
+
47
+ ##
48
+ #
49
+ # Returns a partial SPARQL grammar for this operator.
50
+ #
51
+ # @return [String]
52
+ def to_sparql(**options)
53
+ "ROUND(#{operands.to_sparql(**options)})"
54
+ end
32
55
  end # Operator
33
56
  end; end # SPARQL::Algebra
@@ -3,12 +3,21 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL `sameTerm` operator.
5
5
  #
6
- # @example
7
- # (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
8
- # (: <http://example.org/things#>))
9
- # (project (?x ?v)
10
- # (filter (sameTerm ?v)
11
- # (bgp (triple ?x :p ?v)))))
6
+ # [121] BuiltInCall ::= ... | 'sameTerm' '(' Expression ',' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/things#>
10
+ # SELECT * {
11
+ # ?x1 :p ?v1 .
12
+ # ?x2 :p ?v2 .
13
+ # FILTER sameTerm(?v1, ?v2)
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix
18
+ # ((: <http://example.org/things#>))
19
+ # (filter (sameTerm ?v1 ?v2)
20
+ # (bgp (triple ?x1 :p ?v1) (triple ?x2 :p ?v2))))
12
21
  #
13
22
  # @see https://www.w3.org/TR/sparql11-query/#func-sameTerm
14
23
  class SameTerm < Operator::Binary
@@ -26,7 +35,7 @@ module SPARQL; module Algebra
26
35
  # an RDF term
27
36
  # @return [RDF::Literal::Boolean] `true` or `false`
28
37
  # @raise [TypeError] if either operand is unbound
29
- def apply(term1, term2)
38
+ def apply(term1, term2, **options)
30
39
  RDF::Literal(term1.eql?(term2))
31
40
  end
32
41
 
@@ -44,6 +53,15 @@ module SPARQL; module Algebra
44
53
  super # @see Operator#optimize!
45
54
  end
46
55
  end
56
+
57
+ ##
58
+ #
59
+ # Returns a partial SPARQL grammar for this operator.
60
+ #
61
+ # @return [String]
62
+ def to_sparql(**options)
63
+ "sameTerm(#{operands.to_sparql(delimiter: ', ', **options)})"
64
+ end
47
65
  end # SameTerm
48
66
  end # Operator
49
67
  end; end # SPARQL::Algebra