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.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -28
  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 +4 -1
  8. data/lib/sparql/algebra/extensions.rb +96 -29
  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 +18 -2
  16. data/lib/sparql/algebra/operator/base.rb +18 -1
  17. data/lib/sparql/algebra/operator/bgp.rb +5 -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 +16 -2
  22. data/lib/sparql/algebra/operator/coalesce.rb +33 -11
  23. data/lib/sparql/algebra/operator/compare.rb +48 -33
  24. data/lib/sparql/algebra/operator/concat.rb +26 -2
  25. data/lib/sparql/algebra/operator/construct.rb +31 -7
  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 +18 -2
  29. data/lib/sparql/algebra/operator/create.rb +19 -2
  30. data/lib/sparql/algebra/operator/dataset.rb +17 -0
  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 +27 -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 +18 -1
  39. data/lib/sparql/algebra/operator/divide.rb +27 -3
  40. data/lib/sparql/algebra/operator/drop.rb +17 -2
  41. data/lib/sparql/algebra/operator/encode_for_uri.rb +25 -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 +12 -1
  45. data/lib/sparql/algebra/operator/extend.rb +33 -18
  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/graph.rb +13 -0
  49. data/lib/sparql/algebra/operator/greater_than.rb +14 -4
  50. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +14 -4
  51. data/lib/sparql/algebra/operator/group.rb +34 -8
  52. data/lib/sparql/algebra/operator/group_concat.rb +20 -8
  53. data/lib/sparql/algebra/operator/hours.rb +24 -6
  54. data/lib/sparql/algebra/operator/if.rb +21 -4
  55. data/lib/sparql/algebra/operator/in.rb +18 -1
  56. data/lib/sparql/algebra/operator/insert.rb +22 -2
  57. data/lib/sparql/algebra/operator/insert_data.rb +23 -2
  58. data/lib/sparql/algebra/operator/iri.rb +22 -5
  59. data/lib/sparql/algebra/operator/is_blank.rb +20 -2
  60. data/lib/sparql/algebra/operator/is_iri.rb +20 -2
  61. data/lib/sparql/algebra/operator/is_literal.rb +20 -2
  62. data/lib/sparql/algebra/operator/is_numeric.rb +22 -4
  63. data/lib/sparql/algebra/operator/is_triple.rb +62 -0
  64. data/lib/sparql/algebra/operator/join.rb +22 -1
  65. data/lib/sparql/algebra/operator/lang.rb +26 -1
  66. data/lib/sparql/algebra/operator/lang_matches.rb +23 -2
  67. data/lib/sparql/algebra/operator/lcase.rb +24 -3
  68. data/lib/sparql/algebra/operator/left_join.rb +29 -1
  69. data/lib/sparql/algebra/operator/less_than.rb +14 -4
  70. data/lib/sparql/algebra/operator/less_than_or_equal.rb +14 -4
  71. data/lib/sparql/algebra/operator/load.rb +25 -2
  72. data/lib/sparql/algebra/operator/max.rb +18 -2
  73. data/lib/sparql/algebra/operator/md5.rb +23 -6
  74. data/lib/sparql/algebra/operator/min.rb +19 -3
  75. data/lib/sparql/algebra/operator/minus.rb +25 -7
  76. data/lib/sparql/algebra/operator/minutes.rb +24 -6
  77. data/lib/sparql/algebra/operator/modify.rb +41 -5
  78. data/lib/sparql/algebra/operator/month.rb +24 -6
  79. data/lib/sparql/algebra/operator/move.rb +20 -2
  80. data/lib/sparql/algebra/operator/multiply.rb +27 -4
  81. data/lib/sparql/algebra/operator/negate.rb +24 -4
  82. data/lib/sparql/algebra/operator/not.rb +25 -4
  83. data/lib/sparql/algebra/operator/not_equal.rb +16 -1
  84. data/lib/sparql/algebra/operator/notexists.rb +30 -6
  85. data/lib/sparql/algebra/operator/notin.rb +20 -3
  86. data/lib/sparql/algebra/operator/notoneof.rb +12 -2
  87. data/lib/sparql/algebra/operator/now.rb +25 -6
  88. data/lib/sparql/algebra/operator/object.rb +59 -0
  89. data/lib/sparql/algebra/operator/or.rb +26 -3
  90. data/lib/sparql/algebra/operator/order.rb +27 -2
  91. data/lib/sparql/algebra/operator/path.rb +29 -2
  92. data/lib/sparql/algebra/operator/path_opt.rb +21 -2
  93. data/lib/sparql/algebra/operator/path_plus.rb +21 -2
  94. data/lib/sparql/algebra/operator/path_star.rb +20 -2
  95. data/lib/sparql/algebra/operator/plus.rb +43 -4
  96. data/lib/sparql/algebra/operator/predicate.rb +59 -0
  97. data/lib/sparql/algebra/operator/prefix.rb +24 -3
  98. data/lib/sparql/algebra/operator/project.rb +51 -5
  99. data/lib/sparql/algebra/operator/rand.rb +31 -3
  100. data/lib/sparql/algebra/operator/reduced.rb +18 -1
  101. data/lib/sparql/algebra/operator/regex.rb +27 -19
  102. data/lib/sparql/algebra/operator/replace.rb +27 -7
  103. data/lib/sparql/algebra/operator/reverse.rb +20 -2
  104. data/lib/sparql/algebra/operator/round.rb +26 -3
  105. data/lib/sparql/algebra/operator/same_term.rb +25 -7
  106. data/lib/sparql/algebra/operator/sample.rb +31 -9
  107. data/lib/sparql/algebra/operator/seconds.rb +24 -6
  108. data/lib/sparql/algebra/operator/seq.rb +20 -2
  109. data/lib/sparql/algebra/operator/sequence.rb +0 -10
  110. data/lib/sparql/algebra/operator/sha1.rb +19 -2
  111. data/lib/sparql/algebra/operator/sha256.rb +19 -2
  112. data/lib/sparql/algebra/operator/sha384.rb +19 -2
  113. data/lib/sparql/algebra/operator/sha512.rb +19 -2
  114. data/lib/sparql/algebra/operator/slice.rb +27 -5
  115. data/lib/sparql/algebra/operator/str.rb +22 -2
  116. data/lib/sparql/algebra/operator/strafter.rb +26 -3
  117. data/lib/sparql/algebra/operator/strbefore.rb +26 -3
  118. data/lib/sparql/algebra/operator/strdt.rb +23 -2
  119. data/lib/sparql/algebra/operator/strends.rb +26 -4
  120. data/lib/sparql/algebra/operator/strlang.rb +26 -7
  121. data/lib/sparql/algebra/operator/strlen.rb +24 -3
  122. data/lib/sparql/algebra/operator/strstarts.rb +26 -3
  123. data/lib/sparql/algebra/operator/struuid.rb +30 -10
  124. data/lib/sparql/algebra/operator/subject.rb +61 -0
  125. data/lib/sparql/algebra/operator/substr.rb +24 -3
  126. data/lib/sparql/algebra/operator/subtract.rb +29 -3
  127. data/lib/sparql/algebra/operator/sum.rb +18 -2
  128. data/lib/sparql/algebra/operator/table.rb +42 -4
  129. data/lib/sparql/algebra/operator/timezone.rb +24 -6
  130. data/lib/sparql/algebra/operator/tz.rb +23 -6
  131. data/lib/sparql/algebra/operator/ucase.rb +24 -3
  132. data/lib/sparql/algebra/operator/union.rb +29 -6
  133. data/lib/sparql/algebra/operator/update.rb +25 -4
  134. data/lib/sparql/algebra/operator/using.rb +32 -2
  135. data/lib/sparql/algebra/operator/uuid.rb +28 -9
  136. data/lib/sparql/algebra/operator/with.rb +38 -4
  137. data/lib/sparql/algebra/operator/year.rb +24 -6
  138. data/lib/sparql/algebra/operator.rb +112 -7
  139. data/lib/sparql/algebra/sxp_extensions.rb +3 -3
  140. data/lib/sparql/grammar/meta.rb +5390 -2410
  141. data/lib/sparql/grammar/parser11.rb +119 -53
  142. data/lib/sparql/grammar/terminals11.rb +2 -0
  143. data/lib/sparql/grammar.rb +0 -25
  144. metadata +40 -34
@@ -3,8 +3,20 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL logical `ucase` operator.
5
5
  #
6
- # @example
7
- # (ucase ?x)
6
+ # [121] BuiltInCall ::= ... | 'UCASE' '(' Expression ')'
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # SELECT ?s (UCASE(?str) AS ?ustr) WHERE {
11
+ # ?s :str ?str
12
+ # }
13
+ #
14
+ # @example SSE
15
+ # (prefix
16
+ # ((: <http://example.org/>))
17
+ # (project (?str ?ustr)
18
+ # (extend ((?ustr (ucase ?str)))
19
+ # (bgp (triple ?s :str ?str)))))
8
20
  #
9
21
  # @see https://www.w3.org/TR/sparql11-query/#func-ucase
10
22
  # @see https://www.w3.org/TR/xpath-functions/#func-ucase
@@ -20,12 +32,21 @@ module SPARQL; module Algebra
20
32
  # the operand
21
33
  # @return [RDF::Literal] literal of same type
22
34
  # @raise [TypeError] if the operand is not a literal value
23
- def apply(operand)
35
+ def apply(operand, **options)
24
36
  case operand
25
37
  when RDF::Literal then RDF::Literal(operand.to_s.upcase, datatype: operand.datatype, language: operand.language)
26
38
  else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
27
39
  end
28
40
  end
41
+
42
+ ##
43
+ #
44
+ # Returns a partial SPARQL grammar for this operator.
45
+ #
46
+ # @return [String]
47
+ def to_sparql(**options)
48
+ "UCASE(" + operands.last.to_sparql(**options) + ")"
49
+ end
29
50
  end # UCase
30
51
  end # Operator
31
52
  end; end # SPARQL::Algebra
@@ -3,12 +3,19 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `union` operator.
5
5
  #
6
- # @example
7
- # (prefix ((: <http://example/>))
8
- # (union
9
- # (bgp (triple ?s ?p ?o))
10
- # (graph ?g
11
- # (bgp (triple ?s ?p ?o)))))
6
+ # [67] GroupOrUnionGraphPattern::= GroupGraphPattern ( 'UNION' GroupGraphPattern )*
7
+ #
8
+ # @example SPARQL Grammar
9
+ # SELECT * {
10
+ # { ?s ?p ?o }
11
+ # UNION
12
+ # { GRAPH ?g { ?s ?p ?o } }}
13
+ #
14
+ # @example SSE
15
+ # (union
16
+ # (bgp (triple ?s ?p ?o))
17
+ # (graph ?g
18
+ # (bgp (triple ?s ?p ?o))))
12
19
  #
13
20
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
14
21
  class Union < Operator::Binary
@@ -66,6 +73,22 @@ module SPARQL; module Algebra
66
73
  @operands = ops
67
74
  self
68
75
  end
76
+
77
+ ##
78
+ #
79
+ # Returns a partial SPARQL grammar for this operator.
80
+ #
81
+ # @param [Boolean] top_level (true)
82
+ # Treat this as a top-level, generating SELECT ... WHERE {}
83
+ # @return [String]
84
+ def to_sparql(top_level: true, **options)
85
+ str = "{\n"
86
+ str << operands[0].to_sparql(top_level: false, **options)
87
+ str << "\n} UNION {\n"
88
+ str << operands[1].to_sparql(top_level: false, **options)
89
+ str << "\n}"
90
+ top_level ? Operator.to_sparql(str, **options) : str
91
+ end
69
92
  end # Union
70
93
  end # Operator
71
94
  end; end # SPARQL::Algebra
@@ -3,11 +3,23 @@ module SPARQL; module Algebra
3
3
  ##
4
4
  # The SPARQL GraphPattern `prefix` operator.
5
5
  #
6
- # @example
7
- # (update
6
+ # [29] Update ::= Prologue ( Update1 ( ';' Update )? )?
7
+ #
8
+ # @example SPARQL Grammar
9
+ # PREFIX : <http://example.org/>
10
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
11
+ # DELETE { ?a foaf:knows ?b }
12
+ # INSERT { ?b foaf:knows ?a }
13
+ # WHERE { ?a foaf:knows ?b }
14
+ #
15
+ # @example SSE
16
+ # (prefix ((: <http://example.org/>)
17
+ # (foaf: <http://xmlns.com/foaf/0.1/>))
18
+ # (update
8
19
  # (modify
9
- # (bgp (triple ?s ?p ?o))
10
- # (insert ((triple ?s ?p "q")))))
20
+ # (bgp (triple ?a foaf:knows ?b))
21
+ # (delete ((triple ?a foaf:knows ?b)))
22
+ # (insert ((triple ?b foaf:knows ?a)))) ))
11
23
  #
12
24
  # @see https://www.w3.org/TR/sparql11-update/#graphUpdate
13
25
  class Update < Operator
@@ -39,6 +51,15 @@ module SPARQL; module Algebra
39
51
  end
40
52
  queryable
41
53
  end
54
+
55
+ ##
56
+ #
57
+ # Returns a partial SPARQL grammar for this operator.
58
+ #
59
+ # @return [String]
60
+ def to_sparql(**options)
61
+ str = operands.map { |e| e.to_sparql(**options) }.join("\n")
62
+ end
42
63
  end # Update
43
64
  end # Operator
44
65
  end; end # SPARQL::Algebra
@@ -6,8 +6,27 @@ module SPARQL; module Algebra
6
6
  #
7
7
  # The USING and USING NAMED clauses affect the RDF Dataset used while evaluating the WHERE clause. This describes a dataset in the same way as FROM and FROM NAMED clauses describe RDF Datasets in the SPARQL 1.1 Query Language
8
8
  #
9
- # @example
10
- # (using (:g1) (bgp (triple ?s ?p ?o)))
9
+ # [44] UsingClause ::= 'USING' ( iri | 'NAMED' iri )
10
+ #
11
+ # @example SPARQL Grammar
12
+ # PREFIX : <http://example.org/>
13
+ # PREFIX foaf: <http://xmlns.com/foaf/0.1/>
14
+ #
15
+ # DELETE { ?s ?p ?o }
16
+ # USING <http://example.org/g2>
17
+ # WHERE {
18
+ # :a foaf:knows ?s .
19
+ # ?s ?p ?o
20
+ # }
21
+ #
22
+ # @example SSE
23
+ # (prefix
24
+ # ((: <http://example.org/>) (foaf: <http://xmlns.com/foaf/0.1/>))
25
+ # (update
26
+ # (modify
27
+ # (using (:g2)
28
+ # (bgp (triple :a foaf:knows ?s) (triple ?s ?p ?o)))
29
+ # (delete ((triple ?s ?p ?o)))) ))
11
30
  #
12
31
  # @see https://www.w3.org/TR/sparql11-update/#add
13
32
  class Using < Operator
@@ -35,6 +54,17 @@ module SPARQL; module Algebra
35
54
  debug(options) {"Using"}
36
55
  Dataset.new(*operands).execute(queryable, depth: options[:depth].to_i + 1, **options, &block)
37
56
  end
57
+
58
+ ##
59
+ #
60
+ # Returns a partial SPARQL grammar for this operator.
61
+ #
62
+ # @return [String]
63
+ def to_sparql(**options)
64
+ str = "USING #{operands.first.to_sparql(**options)}\n"
65
+ content = operands.last.to_sparql(top_level: false, **options)
66
+ str << Operator.to_sparql(content, project: nil, **options)
67
+ end
38
68
  end # Using
39
69
  end # Operator
40
70
  end; end # SPARQL::Algebra
@@ -5,14 +5,24 @@ module SPARQL; module Algebra
5
5
  ##
6
6
  # The SPARQL `uuid` function.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>)
10
- # (xsd: <http://www.w3.org/2001/XMLSchema#>))
11
- # (project (?length)
12
- # (extend ((?length (strlen (str ?uuid))))
13
- # (filter (&& (isIRI ?uuid) (regex (str ?uuid) "^urn:uuid:[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$" "i"))
14
- # (extend ((?uuid (uuid)))
15
- # (bgp))))))
8
+ # [121] BuiltInCall ::= ... | 'UUID' NIL
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
13
+ # ASK {
14
+ # BIND(UUID() AS ?u1)
15
+ # BIND(UUID() AS ?u2)
16
+ # FILTER(?u1 != ?u2)
17
+ # }
18
+ #
19
+ # @example SSE
20
+ # (prefix
21
+ # ((: <http://example.org/>) (xsd: <http://www.w3.org/2001/XMLSchema#>))
22
+ # (ask
23
+ # (filter (!= ?u1 ?u2)
24
+ # (extend ((?u1 (uuid)) (?u2 (uuid)))
25
+ # (bgp)))))
16
26
  #
17
27
  # @see https://www.w3.org/TR/sparql11-query/#func-uuid
18
28
  class UUID < Operator::Nullary
@@ -24,9 +34,18 @@ module SPARQL; module Algebra
24
34
  # Return a fresh IRI from the UUID URN scheme. Each call of UUID() returns a different UUID. It must not be the "nil" UUID (all zeroes). The variant and version of the UUID is implementation dependent.
25
35
  #
26
36
  # @return [RDF::URI]
27
- def apply
37
+ def apply(**options)
28
38
  RDF::URI("urn:uuid:#{SecureRandom.uuid}")
29
39
  end
40
+
41
+ ##
42
+ #
43
+ # Returns a partial SPARQL grammar for this operator.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "UUID(" + operands.to_sparql(delimiter: ', ', **options) + ")"
48
+ end
30
49
  end # UUID
31
50
  end # Operator
32
51
  end; end # SPARQL::Algebra
@@ -6,10 +6,21 @@ module SPARQL; module Algebra
6
6
  #
7
7
  # The WITH clause provides a convenience for when an operation primarily refers to a single graph.
8
8
  #
9
- # @example
10
- # (with :g1
11
- # (bgp (triple ?s ?p ?o))
12
- # (insert ((triple ?s ?p "z"))))
9
+ # [41] Modify ::= ( 'WITH' iri )? ( DeleteClause InsertClause? | InsertClause ) UsingClause* 'WHERE' GroupGraphPattern
10
+ #
11
+ # @example SPARQL Grammar
12
+ # PREFIX : <http://example/>
13
+ # WITH :g
14
+ # DELETE { <base:s> ?p ?o . }
15
+ # WHERE { ?s ?p ?o }
16
+ #
17
+ # @example SSE
18
+ # (prefix ((: <http://example/>))
19
+ # (update
20
+ # (modify
21
+ # (with :g
22
+ # (bgp (triple ?s ?p ?o))
23
+ # (delete ((triple <base:s> ?p ?o)))))))
13
24
  #
14
25
  # @see https://www.w3.org/TR/sparql11-update/#deleteInsert
15
26
  class With < Operator
@@ -67,6 +78,29 @@ module SPARQL; module Algebra
67
78
  end
68
79
  end
69
80
  end
81
+
82
+ ##
83
+ #
84
+ # Returns a partial SPARQL grammar for this operator.
85
+ #
86
+ # @return [String]
87
+ def to_sparql(**options)
88
+ with, where, ops = operands
89
+ str = "WITH #{with.to_sparql(**options)}\n"
90
+
91
+ # The content of the WHERE clause, may be USING
92
+ content = where.to_sparql(top_level: false, **options)
93
+
94
+ # DELETE | INSERT | DELETE INSERT
95
+ str << ops.to_sparql(top_level: false, delimiter: "\n", **options) + "\n"
96
+
97
+ # Append the WHERE or USING clause
98
+ str << if where.is_a?(Using)
99
+ content
100
+ else
101
+ Operator.to_sparql(content, project: nil, **options)
102
+ end
103
+ end
70
104
  end # With
71
105
  end # Operator
72
106
  end; end # SPARQL::Algebra
@@ -5,11 +5,20 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # Returns the year part of `arg` as an integer.
7
7
  #
8
- # @example
9
- # (prefix ((: <http://example.org/>))
10
- # (project (?s ?x)
11
- # (extend ((?x (year ?date)))
12
- # (bgp (triple ?s :date ?date)))))
8
+ # [121] BuiltInCall ::= ... | 'YEAR' '(' Expression ')'
9
+ #
10
+ # @example SPARQL Grammar
11
+ # PREFIX : <http://example.org/>
12
+ # SELECT ?s (YEAR(?date) AS ?x) WHERE {
13
+ # ?s :date ?date
14
+ # }
15
+ #
16
+ # @example SSE
17
+ # (prefix
18
+ # ((: <http://example.org/>))
19
+ # (project (?s ?x)
20
+ # (extend ((?x (year ?date)))
21
+ # (bgp (triple ?s :date ?date)))))
13
22
  #
14
23
  # @see https://www.w3.org/TR/sparql11-query/#func-year
15
24
  class Year < Operator::Unary
@@ -24,10 +33,19 @@ module SPARQL; module Algebra
24
33
  # the operand
25
34
  # @return [RDF::Literal]
26
35
  # @raise [TypeError] if the operand is not a simple literal
27
- def apply(operand)
36
+ def apply(operand, **options)
28
37
  raise TypeError, "expected an RDF::Literal::DateTime, but got #{operand.inspect}" unless operand.is_a?(RDF::Literal::DateTime)
29
38
  RDF::Literal(operand.object.year)
30
39
  end
40
+
41
+ ##
42
+ #
43
+ # Returns a partial SPARQL grammar for this operator.
44
+ #
45
+ # @return [String]
46
+ def to_sparql(**options)
47
+ "YEAR(#{operands.last.to_sparql(**options)})"
48
+ end
31
49
  end # Year
32
50
  end # Operator
33
51
  end; end # SPARQL::Algebra
@@ -49,11 +49,16 @@ module SPARQL; module Algebra
49
49
  autoload :Sum, 'sparql/algebra/operator/sum'
50
50
  autoload :SHA1, 'sparql/algebra/operator/sha1'
51
51
  autoload :SHA256, 'sparql/algebra/operator/sha256'
52
+ autoload :SHA384, 'sparql/algebra/operator/sha384'
52
53
  autoload :SHA512, 'sparql/algebra/operator/sha512'
53
54
  autoload :Str, 'sparql/algebra/operator/str'
54
55
  autoload :Timezone, 'sparql/algebra/operator/timezone'
55
56
  autoload :TZ, 'sparql/algebra/operator/tz'
56
57
  autoload :Year, 'sparql/algebra/operator/year'
58
+ autoload :IsTriple, 'sparql/algebra/operator/is_triple'
59
+ autoload :Subject, 'sparql/algebra/operator/subject'
60
+ autoload :Predicate, 'sparql/algebra/operator/predicate'
61
+ autoload :Object, 'sparql/algebra/operator/object'
57
62
 
58
63
  # Binary operators
59
64
  autoload :And, 'sparql/algebra/operator/and'
@@ -167,7 +172,6 @@ module SPARQL; module Algebra
167
172
  when :> then GreaterThan
168
173
  when :>= then GreaterThanOrEqual
169
174
  when :abs then Abs
170
- when :add then Add
171
175
  when :alt then Alt
172
176
  when :and, :'&&' then And
173
177
  when :avg then Avg
@@ -200,7 +204,6 @@ module SPARQL; module Algebra
200
204
  when :md5 then MD5
201
205
  when :max then Max
202
206
  when :min then Min
203
- when :minus then Minus
204
207
  when :minutes then Minutes
205
208
  when :month then Month
206
209
  when :multiply then Multiply
@@ -227,6 +230,7 @@ module SPARQL; module Algebra
227
230
  when :sequence then Sequence
228
231
  when :sha1 then SHA1
229
232
  when :sha256 then SHA256
233
+ when :sha384 then SHA384
230
234
  when :sha512 then SHA512
231
235
  when :str then Str
232
236
  when :strafter then StrAfter
@@ -274,7 +278,6 @@ module SPARQL; module Algebra
274
278
  when :reduced then Reduced
275
279
  when :slice then Slice
276
280
  when :table then Table
277
- when :triple then RDF::Query::Pattern
278
281
  when :union then Union
279
282
 
280
283
  # Update forms
@@ -294,6 +297,14 @@ module SPARQL; module Algebra
294
297
  when :update then Update
295
298
  when :using then Using
296
299
  when :with then With
300
+
301
+ # RDF-star
302
+ when :istriple then IsTriple
303
+ when :triple then RDF::Query::Pattern
304
+ when :subject then Subject
305
+ when :predicate then Predicate
306
+ when :object then Object
307
+
297
308
  else nil # not found
298
309
  end
299
310
  end
@@ -302,8 +313,8 @@ module SPARQL; module Algebra
302
313
  # @param [Array<RDF::Term>] operands
303
314
  # @return [RDF::Term]
304
315
  # @see Operator#evaluate
305
- def self.evaluate(*operands)
306
- self.new(*operands).evaluate(RDF::Query::Solution.new)
316
+ def self.evaluate(*operands, **options)
317
+ self.new(*operands, **options).evaluate(RDF::Query::Solution.new, **options)
307
318
  end
308
319
 
309
320
  ##
@@ -321,6 +332,89 @@ module SPARQL; module Algebra
321
332
  self.const_get(:ARITY)
322
333
  end
323
334
 
335
+ ##
336
+ # Generate a top-level Grammar, using collected options
337
+ #
338
+ # @param [String] content
339
+ # @param [Hash{Symbol => Operator}] extensions
340
+ # Variable bindings
341
+ # @param [Operator] distinct (false)
342
+ # @param [Array<Operator>] filter_ops ([])
343
+ # Filter Operations
344
+ # @param [Integer] limit (nil)
345
+ # @param [Array<Operator>] group_ops ([])
346
+ # @param [Integer] offset (nil)
347
+ # @param [Array<Operator>] order_ops ([])
348
+ # Order Operations
349
+ # @param [Array<Symbol,Operator>] project (%i(*))
350
+ # Terms to project
351
+ # @param [Operator] reduced (false)
352
+ # @param [Hash{Symbol => Object}] options
353
+ # @return [String]
354
+ def self.to_sparql(content,
355
+ distinct: false,
356
+ extensions: {},
357
+ filter_ops: [],
358
+ group_ops: [],
359
+ limit: nil,
360
+ offset: nil,
361
+ order_ops: [],
362
+ project: %i(*),
363
+ reduced: false,
364
+ **options)
365
+ str = ""
366
+
367
+ # Projections
368
+ if project
369
+ str << "SELECT "
370
+ str << "DISTINCT " if distinct
371
+ str << "REDUCED " if reduced
372
+
373
+ str << project.map do |p|
374
+ if expr = extensions.delete(p)
375
+ # Replace projected variables with their extension, if any
376
+ "(" + [expr, :AS, p].to_sparql(**options) + ")"
377
+ else
378
+ p.to_sparql(**options)
379
+ end
380
+ end.join(" ") + "\n"
381
+ end
382
+
383
+ # Extensions
384
+ extensions.each do |as, expression|
385
+ content << "\nBIND (#{expression.to_sparql(**options)} AS #{as.to_sparql(**options)}) ."
386
+ end
387
+
388
+ # Filters
389
+ filter_ops.each do |f|
390
+ content << "\nFILTER #{f.to_sparql(**options)} ."
391
+ end
392
+
393
+ # Where clause
394
+ str << "WHERE {\n#{content}\n}\n"
395
+
396
+ # Group
397
+ unless group_ops.empty?
398
+ ops = group_ops.map do |o|
399
+ # Replace projected variables with their extension, if any
400
+ o.is_a?(Array) ?
401
+ "(" + [o.last, :AS, o.first].to_sparql(**options) + ")" :
402
+ o.to_sparql(**options)
403
+ end
404
+ str << "GROUP BY #{ops.join(' ')}\n"
405
+ end
406
+
407
+ # Order
408
+ unless order_ops.empty?
409
+ str << "ORDER BY #{order_ops.to_sparql(**options)}\n"
410
+ end
411
+
412
+ # Offset and Limmit
413
+ str << "OFFSET #{offset}\n" unless offset.nil?
414
+ str << "LIMIT #{limit}\n" unless limit.nil?
415
+ str
416
+ end
417
+
324
418
  ARITY = -1 # variable arity
325
419
 
326
420
  ##
@@ -569,9 +663,20 @@ module SPARQL; module Algebra
569
663
  ##
570
664
  # Returns an S-Expression (SXP) representation of this operator
571
665
  #
666
+ # @param [Hash{Symbol => RDF::URI}] prefixes (nil)
667
+ # @param [RDF::URI] base_uri (nil)
668
+ # @return [String]
669
+ def to_sxp(prefixes: nil, base_uri: nil)
670
+ to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
671
+ end
672
+
673
+ ##
674
+ #
675
+ # Returns a partial SPARQL grammar for the operator.
676
+ #
572
677
  # @return [String]
573
- def to_sxp
574
- to_sxp_bin.to_sxp
678
+ def to_sparql(**options)
679
+ raise NotImplementedError, "#{self.class}#to_sparql(#{operands.map(&:class).join(', ')})"
575
680
  end
576
681
 
577
682
  ##
@@ -5,7 +5,7 @@ class NilClass
5
5
  # Returns the SXP representation of this object.
6
6
  #
7
7
  # @return [String]
8
- def to_sxp
8
+ def to_sxp(**options)
9
9
  RDF.nil.to_s
10
10
  end
11
11
  end
@@ -17,7 +17,7 @@ class FalseClass
17
17
  # Returns the SXP representation of this object.
18
18
  #
19
19
  # @return [String]
20
- def to_sxp
20
+ def to_sxp(**options)
21
21
  'false'
22
22
  end
23
23
  end
@@ -29,7 +29,7 @@ class TrueClass
29
29
  # Returns the SXP representation of this object.
30
30
  #
31
31
  # @return [String]
32
- def to_sxp
32
+ def to_sxp(**options)
33
33
  'true'
34
34
  end
35
35
  end