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
@@ -6,6 +6,19 @@ module SPARQL; module Algebra
|
|
6
6
|
module Expression
|
7
7
|
include RDF::Util::Logger
|
8
8
|
|
9
|
+
# Operators for which `:triple` denotes a pattern, not a builtin
|
10
|
+
PATTERN_PARENTS = [
|
11
|
+
Operator::BGP,
|
12
|
+
Operator::Construct,
|
13
|
+
Operator::Delete,
|
14
|
+
Operator::DeleteData,
|
15
|
+
Operator::DeleteWhere,
|
16
|
+
Operator::Graph,
|
17
|
+
Operator::Insert,
|
18
|
+
Operator::InsertData,
|
19
|
+
Operator::Path,
|
20
|
+
].freeze
|
21
|
+
|
9
22
|
##
|
10
23
|
# @example
|
11
24
|
# Expression.parse('(isLiteral 3.1415)')
|
@@ -66,9 +79,11 @@ module SPARQL; module Algebra
|
|
66
79
|
#
|
67
80
|
# @param [Array] sse
|
68
81
|
# a SPARQL S-Expression (SSE) form
|
82
|
+
# @param [Hash{Symbol => Object}] options
|
83
|
+
# any additional options (see {Operator#initialize})
|
69
84
|
# @return [Expression]
|
70
|
-
def self.for(*sse)
|
71
|
-
self.new(sse)
|
85
|
+
def self.for(*sse, **options)
|
86
|
+
self.new(sse, **options)
|
72
87
|
end
|
73
88
|
class << self; alias_method :[], :for; end
|
74
89
|
|
@@ -82,20 +97,27 @@ module SPARQL; module Algebra
|
|
82
97
|
# any additional options (see {Operator#initialize})
|
83
98
|
# @return [Expression]
|
84
99
|
# @raise [TypeError] if any of the operands is invalid
|
85
|
-
def self.new(sse, **options)
|
100
|
+
def self.new(sse, parent_operator: nil, **options)
|
86
101
|
raise ArgumentError, "invalid SPARQL::Algebra::Expression form: #{sse.inspect}" unless sse.is_a?(Array)
|
87
102
|
|
88
103
|
operator = Operator.for(sse.first, sse.length - 1)
|
104
|
+
|
105
|
+
# If we don't find an operator, and sse.first is an extension IRI, use a function call
|
106
|
+
if !operator && sse.first.is_a?(RDF::URI) && self.extension?(sse.first)
|
107
|
+
operator = Operator.for(:function_call, sse.length)
|
108
|
+
sse.unshift(:function_call)
|
109
|
+
end
|
110
|
+
|
89
111
|
unless operator
|
90
112
|
return case sse.first
|
91
113
|
when Array
|
92
114
|
debug(options) {"Map array elements #{sse}"}
|
93
|
-
sse.map {|s| self.new(s, depth: options[:depth].to_i + 1, **options)}
|
115
|
+
sse.map {|s| self.new(s, parent_operator: parent_operator, depth: options[:depth].to_i + 1, **options)}
|
94
116
|
else
|
95
117
|
debug(options) {"No operator found for #{sse.first}"}
|
96
118
|
sse.map do |s|
|
97
119
|
s.is_a?(Array) ?
|
98
|
-
self.new(s, depth: options[:depth].to_i + 1) :
|
120
|
+
self.new(s, parent_operator: parent_operator, depth: options[:depth].to_i + 1) :
|
99
121
|
s
|
100
122
|
end
|
101
123
|
end
|
@@ -105,7 +127,7 @@ module SPARQL; module Algebra
|
|
105
127
|
debug(options) {"Operator=#{operator.inspect}, Operand=#{operand.inspect}"}
|
106
128
|
case operand
|
107
129
|
when Array
|
108
|
-
self.new(operand, depth: options[:depth].to_i + 1, **options)
|
130
|
+
self.new(operand, parent_operator: operator, depth: options[:depth].to_i + 1, **options)
|
109
131
|
when Operator, Variable, RDF::Term, RDF::Query, Symbol
|
110
132
|
operand
|
111
133
|
when TrueClass, FalseClass, Numeric, String, DateTime, Date, Time
|
@@ -115,11 +137,22 @@ module SPARQL; module Algebra
|
|
115
137
|
end
|
116
138
|
|
117
139
|
debug(options) {"#{operator.inspect}(#{operands.map(&:inspect).join(',')})"}
|
140
|
+
logger = options[:logger]
|
118
141
|
options.delete_if {|k, v| [:debug, :logger, :depth, :prefixes, :base_uri, :update, :validate].include?(k) }
|
119
142
|
begin
|
120
|
-
|
143
|
+
# Due to confusiong over (triple) and special-case for (qtriple)
|
144
|
+
if operator == RDF::Query::Pattern
|
145
|
+
options = options.merge(quoted: true) if sse.first == :qtriple
|
146
|
+
elsif operator == Operator::Triple && PATTERN_PARENTS.include?(parent_operator)
|
147
|
+
operator = RDF::Query::Pattern
|
148
|
+
end
|
149
|
+
operator.new(*operands, parent_operator: operator, **options)
|
121
150
|
rescue ArgumentError => e
|
122
|
-
|
151
|
+
if logger
|
152
|
+
logger.error("Operator=#{operator.inspect}: #{e}")
|
153
|
+
else
|
154
|
+
raise "Operator=#{operator.inspect}: #{e}"
|
155
|
+
end
|
123
156
|
end
|
124
157
|
end
|
125
158
|
|
@@ -163,6 +196,17 @@ module SPARQL; module Algebra
|
|
163
196
|
@extensions ||= {}
|
164
197
|
end
|
165
198
|
|
199
|
+
##
|
200
|
+
# Is an extension function available?
|
201
|
+
#
|
202
|
+
# It's either a registered extension, or an XSD casting function
|
203
|
+
#
|
204
|
+
# @param [RDF::URI] function
|
205
|
+
# @return [Boolean]
|
206
|
+
def self.extension?(function)
|
207
|
+
function.to_s.start_with?(RDF::XSD.to_s) || self.extensions[function]
|
208
|
+
end
|
209
|
+
|
166
210
|
##
|
167
211
|
# Invoke an extension function.
|
168
212
|
#
|
@@ -190,7 +234,7 @@ module SPARQL; module Algebra
|
|
190
234
|
#
|
191
235
|
# @param [RDF::URI] datatype
|
192
236
|
# Datatype to evaluate, one of:
|
193
|
-
# xsd:integer, xsd:decimal xsd:float, xsd:double, xsd:string, xsd:boolean,
|
237
|
+
# xsd:integer, xsd:decimal xsd:float, xsd:double, xsd:string, xsd:boolean, xsd:dateTime, xsd:duration, xsd:dayTimeDuration, xsd:yearMonthDuration
|
194
238
|
# @param [RDF::Term] value
|
195
239
|
# Value, which should be a typed literal, where the type must be that specified
|
196
240
|
# @raise [TypeError] if datatype is not a URI or value cannot be cast to datatype
|
@@ -198,7 +242,7 @@ module SPARQL; module Algebra
|
|
198
242
|
# @see https://www.w3.org/TR/sparql11-query/#FunctionMapping
|
199
243
|
def self.cast(datatype, value)
|
200
244
|
case datatype
|
201
|
-
when RDF::XSD.dateTime
|
245
|
+
when RDF::XSD.date, RDF::XSD.time, RDF::XSD.dateTime
|
202
246
|
case value
|
203
247
|
when RDF::Literal::DateTime, RDF::Literal::Date, RDF::Literal::Time
|
204
248
|
RDF::Literal.new(value, datatype: datatype)
|
@@ -207,6 +251,15 @@ module SPARQL; module Algebra
|
|
207
251
|
else
|
208
252
|
RDF::Literal.new(value.value, datatype: datatype, validate: true)
|
209
253
|
end
|
254
|
+
when RDF::XSD.duration, RDF::XSD.dayTimeDuration, RDF::XSD.yearMonthDuration
|
255
|
+
case value
|
256
|
+
when RDF::Literal::Duration, RDF::Literal::DayTimeDuration, RDF::Literal::YearMonthDuration
|
257
|
+
RDF::Literal.new(value, datatype: datatype, validate: true, canonicalize: true)
|
258
|
+
when RDF::Literal::Numeric, RDF::Literal::Boolean, RDF::URI, RDF::Node
|
259
|
+
raise TypeError, "Value #{value.inspect} cannot be cast as #{datatype}"
|
260
|
+
else
|
261
|
+
RDF::Literal.new(value.value, datatype: datatype, validate: true, canonicalize: true)
|
262
|
+
end
|
210
263
|
when RDF::XSD.float, RDF::XSD.double
|
211
264
|
case value
|
212
265
|
when RDF::Literal::Boolean
|
@@ -43,6 +43,15 @@ class Object
|
|
43
43
|
def deep_dup
|
44
44
|
dup
|
45
45
|
end
|
46
|
+
|
47
|
+
##
|
48
|
+
#
|
49
|
+
# Returns a partial SPARQL grammar for this term.
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
def to_sparql(**options)
|
53
|
+
to_sxp(**options)
|
54
|
+
end
|
46
55
|
end
|
47
56
|
|
48
57
|
##
|
@@ -57,20 +66,14 @@ class Array
|
|
57
66
|
end
|
58
67
|
|
59
68
|
##
|
60
|
-
# Evaluates the array using the given variable `bindings`.
|
61
69
|
#
|
62
|
-
#
|
63
|
-
# an XSD datatype, and the second is the expression to be evaluated.
|
64
|
-
# The result is cast as a literal of the appropriate type
|
70
|
+
# Returns a partial SPARQL grammar for this array.
|
65
71
|
#
|
66
|
-
# @param
|
67
|
-
#
|
68
|
-
# @
|
69
|
-
|
70
|
-
|
71
|
-
# @see SPARQL::Algebra::Expression.evaluate
|
72
|
-
def evaluate(bindings, **options)
|
73
|
-
SPARQL::Algebra::Expression.extension(*self.map {|o| o.evaluate(bindings, **options)})
|
72
|
+
# @param [String] delimiter (" ")
|
73
|
+
# If the first element is an IRI, treat it as an extension function
|
74
|
+
# @return [String]
|
75
|
+
def to_sparql(delimiter: " ", **options)
|
76
|
+
map {|e| e.to_sparql(**options)}.join(delimiter)
|
74
77
|
end
|
75
78
|
|
76
79
|
##
|
@@ -121,6 +124,14 @@ class Array
|
|
121
124
|
end
|
122
125
|
def constant?; !(variable?); end
|
123
126
|
|
127
|
+
##
|
128
|
+
# The variables used in this array.
|
129
|
+
#
|
130
|
+
# @return [Hash{Symbol => RDF::Query::Variable}]
|
131
|
+
def variables
|
132
|
+
self.inject({}) {|hash, o| o.respond_to?(:variables) ? hash.merge(o.variables) : hash}
|
133
|
+
end
|
134
|
+
|
124
135
|
##
|
125
136
|
# Does this contain any nodes?
|
126
137
|
#
|
@@ -216,15 +227,6 @@ end
|
|
216
227
|
##
|
217
228
|
# Extensions for Ruby's `Hash` class.
|
218
229
|
class Hash
|
219
|
-
##
|
220
|
-
# Returns the SXP representation of this object, defaults to `self`.
|
221
|
-
#
|
222
|
-
# @return [String]
|
223
|
-
def to_sxp_bin
|
224
|
-
to_a.to_sxp_bin
|
225
|
-
end
|
226
|
-
def to_sxp; to_sxp_bin; end
|
227
|
-
|
228
230
|
##
|
229
231
|
# A duplicate of this hash.
|
230
232
|
#
|
@@ -278,24 +280,19 @@ module RDF::Term
|
|
278
280
|
# @see SPARQL::Algebra::Expression#optimize
|
279
281
|
def optimize(**options)
|
280
282
|
optimized = self.deep_dup
|
281
|
-
optimized.lexical = nil if optimized.respond_to?(:lexical=)
|
282
|
-
optimized
|
283
|
+
#optimized.lexical = nil if optimized.respond_to?(:lexical=)
|
284
|
+
#optimized
|
283
285
|
end
|
284
|
-
end # RDF::Term
|
285
286
|
|
286
|
-
class RDF::Literal::Double
|
287
287
|
##
|
288
|
-
#
|
288
|
+
#
|
289
|
+
# Returns a partial SPARQL grammar for this term.
|
289
290
|
#
|
290
291
|
# @return [String]
|
291
|
-
def
|
292
|
-
|
293
|
-
when nan? then 'nan.0'
|
294
|
-
when infinite? then (infinite? > 0 ? '+inf.0' : '-inf.0')
|
295
|
-
else canonicalize.to_s.downcase
|
296
|
-
end
|
292
|
+
def to_sparql(**options)
|
293
|
+
to_sxp(**options)
|
297
294
|
end
|
298
|
-
end
|
295
|
+
end # RDF::Term
|
299
296
|
|
300
297
|
# Override RDF::Queryable to execute against SPARQL::Algebra::Query elements as well as RDF::Query and RDF::Pattern
|
301
298
|
module RDF::Queryable
|
@@ -343,13 +340,22 @@ module RDF::Queryable
|
|
343
340
|
query_without_sparql(pattern, **options, &block)
|
344
341
|
end
|
345
342
|
end
|
343
|
+
|
344
|
+
##
|
345
|
+
#
|
346
|
+
# Returns a partial SPARQL grammar for this term.
|
347
|
+
#
|
348
|
+
# @return [String]
|
349
|
+
def to_sparql(**options)
|
350
|
+
raise NotImplementedError, "SPARQL::Algebra '#{first}' operator not implemented"
|
351
|
+
end
|
346
352
|
end
|
347
353
|
|
348
354
|
class RDF::Statement
|
349
355
|
# Transform Statement Pattern into an SXP
|
350
356
|
# @return [Array]
|
351
357
|
def to_sxp_bin
|
352
|
-
[ (has_graph? ? :quad : :triple),
|
358
|
+
[ (has_graph? ? :quad : (quoted? ? :qtriple : :triple)),
|
353
359
|
(:inferred if inferred?),
|
354
360
|
subject,
|
355
361
|
predicate,
|
@@ -361,9 +367,21 @@ class RDF::Statement
|
|
361
367
|
##
|
362
368
|
# Returns an S-Expression (SXP) representation
|
363
369
|
#
|
370
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes (nil)
|
371
|
+
# @param [RDF::URI] base_uri (nil)
|
372
|
+
# @return [String]
|
373
|
+
def to_sxp(prefixes: nil, base_uri: nil)
|
374
|
+
to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
|
375
|
+
end
|
376
|
+
|
377
|
+
##
|
378
|
+
#
|
379
|
+
# Returns a partial SPARQL grammar for this term.
|
380
|
+
#
|
364
381
|
# @return [String]
|
365
|
-
def
|
366
|
-
|
382
|
+
def to_sparql(**options)
|
383
|
+
str = to_triple.map {|term| term.to_sparql(**options)}.join(" ")
|
384
|
+
quoted? ? ('<<' + str + '>>') : str
|
367
385
|
end
|
368
386
|
|
369
387
|
##
|
@@ -411,6 +429,40 @@ class RDF::Query
|
|
411
429
|
end
|
412
430
|
end
|
413
431
|
|
432
|
+
##
|
433
|
+
#
|
434
|
+
# Returns a partial SPARQL grammar for this query.
|
435
|
+
#
|
436
|
+
# @param [Boolean] top_level (true)
|
437
|
+
# Treat this as a top-level, generating SELECT ... WHERE {}
|
438
|
+
# @param [Array<Operator>] filter_ops ([])
|
439
|
+
# Filter Operations
|
440
|
+
# @return [String]
|
441
|
+
def to_sparql(top_level: true, filter_ops: [], **options)
|
442
|
+
str = @patterns.map do |e|
|
443
|
+
e.to_sparql(top_level: false, **options) + " . \n"
|
444
|
+
end.join("")
|
445
|
+
str = "GRAPH #{graph_name.to_sparql(**options)} {\n#{str}\n}\n" if graph_name
|
446
|
+
if top_level
|
447
|
+
SPARQL::Algebra::Operator.to_sparql(str, filter_ops: filter_ops, **options)
|
448
|
+
else
|
449
|
+
# Filters
|
450
|
+
filter_ops.each do |op|
|
451
|
+
str << "\nFILTER (#{op.to_sparql(**options)}) ."
|
452
|
+
end
|
453
|
+
|
454
|
+
# Extensons
|
455
|
+
extensions = options.fetch(:extensions, [])
|
456
|
+
extensions.each do |as, expression|
|
457
|
+
v = expression.to_sparql(**options)
|
458
|
+
pp = RDF::Query::Variable.new(as).to_sparql(**options)
|
459
|
+
str << "\nBIND (" << v << " AS " << pp << ") ."
|
460
|
+
end
|
461
|
+
str = "{#{str}}" unless filter_ops.empty? && extensions.empty?
|
462
|
+
str
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
414
466
|
##
|
415
467
|
# Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables
|
416
468
|
#
|
@@ -462,11 +514,11 @@ class RDF::Query
|
|
462
514
|
def optimize!(**options)
|
463
515
|
@patterns = @patterns.map do |pattern|
|
464
516
|
components = pattern.to_quad.map do |term|
|
465
|
-
if term.respond_to?(:lexical=)
|
466
|
-
|
467
|
-
else
|
517
|
+
#if term.respond_to?(:lexical=)
|
518
|
+
# term.dup.instance_eval {@lexical = nil; self}
|
519
|
+
#else
|
468
520
|
term
|
469
|
-
end
|
521
|
+
#end
|
470
522
|
end
|
471
523
|
RDF::Query::Pattern.from(components, **pattern.options)
|
472
524
|
end
|
@@ -530,11 +582,15 @@ class RDF::Query::Variable
|
|
530
582
|
self
|
531
583
|
end
|
532
584
|
|
533
|
-
|
534
|
-
#
|
535
|
-
|
536
|
-
|
537
|
-
|
585
|
+
##
|
586
|
+
#
|
587
|
+
# Returns a partial SPARQL grammar for this term.
|
588
|
+
#
|
589
|
+
# The Non-distinguished form (`??xxx`) is not part of the grammar, so replace with a blank-node
|
590
|
+
#
|
591
|
+
# @return [String]
|
592
|
+
def to_sparql(**options)
|
593
|
+
self.distinguished? ? super : "_:_nd#{self.name}"
|
538
594
|
end
|
539
595
|
end # RDF::Query::Variable
|
540
596
|
|
@@ -576,5 +632,13 @@ class RDF::Query::Solution
|
|
576
632
|
def to_sxp_bin
|
577
633
|
to_a.to_sxp_bin
|
578
634
|
end
|
579
|
-
|
635
|
+
|
636
|
+
# Transform Solution into an SXP
|
637
|
+
#
|
638
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes (nil)
|
639
|
+
# @param [RDF::URI] base_uri (nil)
|
640
|
+
# @return [String]
|
641
|
+
def to_sxp(prefixes: nil, base_uri: nil)
|
642
|
+
to_sxp_bin.to_sxp(prefixes: prefixes, base_uri: base_uri)
|
643
|
+
end
|
580
644
|
end # RDF::Query::Solution
|
@@ -3,8 +3,19 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL logical `abs` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# [121] BuiltInCall ::= ... | 'ABS' '(' Expression ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX : <http://example.org/>
|
10
|
+
# SELECT * WHERE {
|
11
|
+
# ?s :num ?num
|
12
|
+
# FILTER(ABS(?num) >= 2)
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example.org/>))
|
17
|
+
# (filter (>= (abs ?num) 2)
|
18
|
+
# (bgp (triple ?s :num ?num))))
|
8
19
|
#
|
9
20
|
# @see https://www.w3.org/TR/sparql11-query/#func-abs
|
10
21
|
# @see https://www.w3.org/TR/xpath-functions/#func-abs
|
@@ -26,6 +37,15 @@ module SPARQL; module Algebra
|
|
26
37
|
else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
|
27
38
|
end
|
28
39
|
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# Returns a partial SPARQL grammar for this operator.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def to_sparql(**options)
|
47
|
+
"ABS(#{operands.first.to_sparql(**options)})"
|
48
|
+
end
|
29
49
|
end # Abs
|
30
50
|
end # Operator
|
31
51
|
end; end # SPARQL::Algebra
|
@@ -6,8 +6,15 @@ module SPARQL; module Algebra
|
|
6
6
|
#
|
7
7
|
# The ADD operation is a shortcut for inserting all data from an input graph into a destination graph. Data from the input graph is not affected, and initial data from the destination graph, if any, is kept intact.
|
8
8
|
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# [35] Add ::= "ADD" "SILENT"? GraphOrDefault "TO" GraphOrDefault
|
10
|
+
#
|
11
|
+
# @example SPARQL Update
|
12
|
+
# PREFIX : <http://example.org/>
|
13
|
+
# ADD DEFAULT TO :g1
|
14
|
+
#
|
15
|
+
# @example SSE
|
16
|
+
# (prefix ((: <http://example.org/>))
|
17
|
+
# (update (add default :g1)))
|
11
18
|
#
|
12
19
|
# @see https://www.w3.org/TR/sparql11-update/#add
|
13
20
|
class Add < Operator
|
@@ -51,6 +58,18 @@ module SPARQL; module Algebra
|
|
51
58
|
end
|
52
59
|
queryable
|
53
60
|
end
|
61
|
+
|
62
|
+
##
|
63
|
+
#
|
64
|
+
# Returns a partial SPARQL grammar for this operator.
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
def to_sparql(**options)
|
68
|
+
*args, last = operands.dup
|
69
|
+
args += [:TO, last]
|
70
|
+
|
71
|
+
"ADD " + args.to_sparql(**options)
|
72
|
+
end
|
54
73
|
end # Add
|
55
74
|
end # Operator
|
56
75
|
end; end # SPARQL::Algebra
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
##
|
4
|
+
# The SPARQL `adjust` operator.
|
5
|
+
#
|
6
|
+
# [121] BuiltInCall ::= ... | 'ADJUST' '(' Expression ',' Expression ')'
|
7
|
+
#
|
8
|
+
# @example SPARQL Grammar
|
9
|
+
# PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
10
|
+
# SELECT ?id (ADJUST(?d, ?tz) AS ?adjusted) WHERE {
|
11
|
+
# VALUES (?id ?tz ?d) {
|
12
|
+
# (1 "-PT10H"^^xsd:dayTimeDuration "2002-03-07"^^xsd:date)
|
13
|
+
# }
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# @example SSE
|
17
|
+
# (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>))
|
18
|
+
# (project (?id ?adjusted)
|
19
|
+
# (extend ((?adjusted (adjust ?d ?tz)))
|
20
|
+
# (table (vars ?id ?tz ?d)
|
21
|
+
# (row
|
22
|
+
# (?id 1)
|
23
|
+
# (?tz "-PT10H"^^xsd:dayTimeDuration)
|
24
|
+
# (?d "2002-03-07"^^xsd:date))))))
|
25
|
+
#
|
26
|
+
# @see https://www.w3.org/TR/sparql11-query/#func-abs
|
27
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-abs
|
28
|
+
class Adjust < Operator::Binary
|
29
|
+
include Evaluatable
|
30
|
+
|
31
|
+
NAME = [:adjust]
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns the first operand adjusted by the dayTimeDuration of the second operand
|
35
|
+
#
|
36
|
+
# @param [RDF::Literal::Temporal] operand
|
37
|
+
# the operand
|
38
|
+
# @param [RDF::Literal, String] duration
|
39
|
+
# the dayTimeDuration or an empty string.
|
40
|
+
# @return [RDF::Literal] literal of same type
|
41
|
+
# @raise [TypeError] if the operand is not a numeric value
|
42
|
+
def apply(operand, duration, **options)
|
43
|
+
case operand
|
44
|
+
when RDF::Literal::Temporal
|
45
|
+
case duration
|
46
|
+
when RDF::Literal::DayTimeDuration
|
47
|
+
operand.adjust_to_timezone(duration)
|
48
|
+
when RDF::Literal
|
49
|
+
raise TypeError, "expected second operand to be an empty literal, but got #{duration.inspect}" unless duration.to_s.empty?
|
50
|
+
operand.adjust_to_timezone(nil)
|
51
|
+
else
|
52
|
+
raise TypeError, "expected second operand to be an RDF::Literal::DayTimeDuration, but got #{duration.inspect}"
|
53
|
+
end
|
54
|
+
else
|
55
|
+
raise TypeError, "expected first operand to be an RDF::Literal::Temporal, but got #{operand.inspect}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
#
|
61
|
+
# Returns a partial SPARQL grammar for this operator.
|
62
|
+
#
|
63
|
+
# @return [String]
|
64
|
+
def to_sparql(**options)
|
65
|
+
"ADJUST(#{operands.to_sparql(delimiter: ', ', **options)})"
|
66
|
+
end
|
67
|
+
end # Abs
|
68
|
+
end # Operator
|
69
|
+
end; end # SPARQL::Algebra
|
@@ -7,8 +7,23 @@ module SPARQL; module Algebra
|
|
7
7
|
#
|
8
8
|
# eval(Path(X, alt(P,Q), Y)) = Union(eval(Path(X, P, Y)), eval(Path(X, Q, Y)))
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
|
11
|
+
#
|
12
|
+
# @example SPARQL Query
|
13
|
+
# PREFIX : <http://www.example.org/>
|
14
|
+
# SELECT ?t
|
15
|
+
# WHERE {
|
16
|
+
# :a :p1|:p2/:p3|:p4 ?t
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example SSE
|
20
|
+
# (prefix ((: <http://www.example.org/>))
|
21
|
+
# (project (?t)
|
22
|
+
# (path :a
|
23
|
+
# (alt
|
24
|
+
# (alt :p1 (seq :p2 :p3))
|
25
|
+
# :p4)
|
26
|
+
# ?t)))
|
12
27
|
#
|
13
28
|
# @see https://www.w3.org/TR/sparql11-query/#defn_evalPP_alternative
|
14
29
|
class Alt < Operator::Binary
|
@@ -57,6 +72,15 @@ module SPARQL; module Algebra
|
|
57
72
|
query = Union.new(qa, qb)
|
58
73
|
queryable.query(query, depth: options[:depth].to_i + 1, **options, &block)
|
59
74
|
end
|
75
|
+
|
76
|
+
##
|
77
|
+
#
|
78
|
+
# Returns a partial SPARQL grammar for this operator.
|
79
|
+
#
|
80
|
+
# @return [String]
|
81
|
+
def to_sparql(**options)
|
82
|
+
"(#{operands.first.to_sparql(**options)}|#{operands.last.to_sparql(**options)})"
|
83
|
+
end
|
60
84
|
end # Alt
|
61
85
|
end # Operator
|
62
86
|
end; end # SPARQL::Algebra
|
@@ -3,9 +3,22 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL logical `and` operator.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# [112] ConditionalAndExpression::= ValueLogical ( '&&' ValueLogical )*
|
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 { ?a :p ?v .
|
13
|
+
# FILTER ("true"^^xsd:boolean && ?v) .
|
14
|
+
# }
|
15
|
+
#
|
16
|
+
# @example SSE
|
17
|
+
# (prefix
|
18
|
+
# ((xsd: <http://www.w3.org/2001/XMLSchema#>) (: <http://example.org/ns#>))
|
19
|
+
# (project (?a)
|
20
|
+
# (filter (&& true ?v)
|
21
|
+
# (bgp (triple ?a :p ?v)))))
|
9
22
|
#
|
10
23
|
# @see https://www.w3.org/TR/sparql11-query/#func-logical-and
|
11
24
|
# @see https://www.w3.org/TR/sparql11-query/#evaluation
|
@@ -60,6 +73,15 @@ module SPARQL; module Algebra
|
|
60
73
|
else RDF::Literal(left && right)
|
61
74
|
end
|
62
75
|
end
|
76
|
+
|
77
|
+
##
|
78
|
+
#
|
79
|
+
# Returns a partial SPARQL grammar for this operator.
|
80
|
+
#
|
81
|
+
# @return [String]
|
82
|
+
def to_sparql(**options)
|
83
|
+
"(#{operands.first.to_sparql(**options)} && #{operands.last.to_sparql(**options)})"
|
84
|
+
end
|
63
85
|
end # And
|
64
86
|
end # Operator
|
65
87
|
end; end # SPARQL::Algebra
|
@@ -3,7 +3,15 @@ module SPARQL; module Algebra
|
|
3
3
|
##
|
4
4
|
# The SPARQL ascending sort operator.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# [24] OrderCondition ::= ( ( 'ASC' | 'DESC' ) BrackettedExpression ) | ( Constraint | Var )
|
7
|
+
#
|
8
|
+
# @example SPARQL Query
|
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))
|
@@ -27,6 +35,17 @@ module SPARQL; module Algebra
|
|
27
35
|
def evaluate(bindings, **options)
|
28
36
|
operand(0).evaluate(bindings, depth: options[:depth].to_i + 1, **options)
|
29
37
|
end
|
38
|
+
|
39
|
+
##
|
40
|
+
#
|
41
|
+
# Returns a partial SPARQL grammar for this operator.
|
42
|
+
#
|
43
|
+
# Provides order to descendant query.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def to_sparql(**options)
|
47
|
+
"ASC(#{operands.last.to_sparql(**options)})"
|
48
|
+
end
|
30
49
|
end # Asc
|
31
50
|
end # Operator
|
32
51
|
end; end # SPARQL::Algebra
|
@@ -5,7 +5,13 @@ module SPARQL; module Algebra
|
|
5
5
|
#
|
6
6
|
# Applications can use the ASK form to test whether or not a query pattern has a solution. No information is returned about the possible query solutions, just whether or not a solution exists.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# [12] AskQuery ::= 'ASK' DatasetClause* WhereClause ValuesClause
|
9
|
+
#
|
10
|
+
# @example SPARQL Query
|
11
|
+
# PREFIX : <http://example/>
|
12
|
+
# ASK { :x :p ?x }
|
13
|
+
#
|
14
|
+
# @example SSE
|
9
15
|
# (prefix ((: <http://example/>))
|
10
16
|
# (ask
|
11
17
|
# (bgp (triple :x :p ?x))))
|
@@ -41,6 +47,16 @@ module SPARQL; module Algebra
|
|
41
47
|
def query_yields_boolean?
|
42
48
|
true
|
43
49
|
end
|
50
|
+
|
51
|
+
##
|
52
|
+
#
|
53
|
+
# Returns a partial SPARQL grammar for this term.
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
def to_sparql(**options)
|
57
|
+
"ASK\n" +
|
58
|
+
operands.first.to_sparql(top_level: true, project: nil, **options)
|
59
|
+
end
|
44
60
|
end # Ask
|
45
61
|
end # Operator
|
46
62
|
end; end # SPARQL::Algebra
|