sparql 1.1.5 → 1.1.6
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 +36 -32
- data/VERSION +1 -1
- data/bin/sparql +8 -6
- data/lib/sparql.rb +4 -2
- data/lib/sparql/algebra.rb +74 -4
- data/lib/sparql/algebra/aggregate.rb +1 -1
- data/lib/sparql/algebra/evaluatable.rb +1 -1
- data/lib/sparql/algebra/expression.rb +24 -16
- data/lib/sparql/algebra/extensions.rb +37 -9
- data/lib/sparql/algebra/operator.rb +75 -12
- data/lib/sparql/algebra/operator/add.rb +41 -19
- data/lib/sparql/algebra/operator/and.rb +2 -2
- data/lib/sparql/algebra/operator/asc.rb +1 -1
- data/lib/sparql/algebra/operator/ask.rb +1 -1
- data/lib/sparql/algebra/operator/base.rb +1 -1
- data/lib/sparql/algebra/operator/bgp.rb +1 -1
- data/lib/sparql/algebra/operator/bnode.rb +1 -1
- data/lib/sparql/algebra/operator/clear.rb +63 -0
- data/lib/sparql/algebra/operator/coalesce.rb +1 -1
- data/lib/sparql/algebra/operator/concat.rb +3 -3
- data/lib/sparql/algebra/operator/construct.rb +2 -2
- data/lib/sparql/algebra/operator/copy.rb +64 -0
- data/lib/sparql/algebra/operator/create.rb +49 -0
- data/lib/sparql/algebra/operator/dataset.rb +6 -31
- data/lib/sparql/algebra/operator/delete.rb +55 -0
- data/lib/sparql/algebra/operator/delete_data.rb +41 -0
- data/lib/sparql/algebra/operator/delete_where.rb +57 -0
- data/lib/sparql/algebra/operator/distinct.rb +1 -1
- data/lib/sparql/algebra/operator/drop.rb +66 -0
- data/lib/sparql/algebra/operator/exists.rb +2 -2
- data/lib/sparql/algebra/operator/exprlist.rb +1 -1
- data/lib/sparql/algebra/operator/extend.rb +3 -3
- data/lib/sparql/algebra/operator/filter.rb +2 -2
- data/lib/sparql/algebra/operator/graph.rb +39 -5
- data/lib/sparql/algebra/operator/group.rb +5 -5
- data/lib/sparql/algebra/operator/group_concat.rb +1 -1
- data/lib/sparql/algebra/operator/if.rb +3 -3
- data/lib/sparql/algebra/operator/in.rb +1 -1
- data/lib/sparql/algebra/operator/insert.rb +54 -0
- data/lib/sparql/algebra/operator/insert_data.rb +41 -0
- data/lib/sparql/algebra/operator/join.rb +2 -2
- data/lib/sparql/algebra/operator/lcase.rb +1 -1
- data/lib/sparql/algebra/operator/left_join.rb +2 -2
- data/lib/sparql/algebra/operator/load.rb +48 -0
- data/lib/sparql/algebra/operator/minus.rb +2 -2
- data/lib/sparql/algebra/operator/modify.rb +53 -0
- data/lib/sparql/algebra/operator/move.rb +67 -0
- data/lib/sparql/algebra/operator/notexists.rb +1 -1
- data/lib/sparql/algebra/operator/notin.rb +2 -2
- data/lib/sparql/algebra/operator/or.rb +2 -2
- data/lib/sparql/algebra/operator/order.rb +3 -3
- data/lib/sparql/algebra/operator/plus.rb +14 -8
- data/lib/sparql/algebra/operator/prefix.rb +1 -1
- data/lib/sparql/algebra/operator/project.rb +1 -1
- data/lib/sparql/algebra/operator/reduced.rb +1 -1
- data/lib/sparql/algebra/operator/replace.rb +1 -1
- data/lib/sparql/algebra/operator/slice.rb +1 -1
- data/lib/sparql/algebra/operator/strafter.rb +1 -1
- data/lib/sparql/algebra/operator/strbefore.rb +2 -2
- data/lib/sparql/algebra/operator/strdt.rb +1 -1
- data/lib/sparql/algebra/operator/strlang.rb +1 -1
- data/lib/sparql/algebra/operator/substr.rb +2 -2
- data/lib/sparql/algebra/operator/ucase.rb +1 -1
- data/lib/sparql/algebra/operator/union.rb +1 -1
- data/lib/sparql/algebra/operator/update.rb +44 -0
- data/lib/sparql/algebra/operator/using.rb +40 -0
- data/lib/sparql/algebra/operator/with.rb +72 -0
- data/lib/sparql/algebra/update.rb +56 -0
- data/lib/sparql/extensions.rb +8 -8
- data/lib/sparql/grammar.rb +31 -8
- data/lib/sparql/grammar/meta.rb +3758 -3273
- data/lib/sparql/grammar/parser11.rb +240 -46
- data/lib/sparql/grammar/terminals11.rb +5 -5
- data/lib/sparql/results.rb +26 -26
- metadata +38 -30
@@ -28,8 +28,8 @@ module SPARQL; module Algebra
|
|
28
28
|
def evaluate(bindings, options = {})
|
29
29
|
queryable = options[:queryable]
|
30
30
|
!operand(0).execute(queryable, options.merge(
|
31
|
-
:
|
32
|
-
:
|
31
|
+
solutions: RDF::Query::Solutions(bindings),
|
32
|
+
depth: options[:depth].to_i + 1)).empty?
|
33
33
|
end
|
34
34
|
end # Exists
|
35
35
|
end # Operator
|
@@ -37,7 +37,7 @@ module SPARQL; module Algebra
|
|
37
37
|
# @return [RDF::Literal::Boolean] `true` or `false`
|
38
38
|
# @raise [TypeError] if the operands could not be coerced to a boolean literal
|
39
39
|
def evaluate(bindings, options = {})
|
40
|
-
res = operands.all? {|op| boolean(op.evaluate(bindings, options.merge(:
|
40
|
+
res = operands.all? {|op| boolean(op.evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))).true? }
|
41
41
|
RDF::Literal(res) # FIXME: error handling
|
42
42
|
end
|
43
43
|
|
@@ -41,14 +41,14 @@ module SPARQL; module Algebra
|
|
41
41
|
# @see http://www.w3.org/TR/rdf-sparql-query/#evaluation
|
42
42
|
def execute(queryable, options = {}, &block)
|
43
43
|
debug(options) {"Extend"}
|
44
|
-
@solutions = operands.last.execute(queryable, options.merge(:
|
44
|
+
@solutions = operands.last.execute(queryable, options.merge(depth: options[:depth].to_i + 1))
|
45
45
|
@solutions.each do |solution|
|
46
46
|
debug(options) {"===> soln #{solution.to_hash.inspect}"}
|
47
47
|
operands.first.each do |(var, expr)|
|
48
48
|
begin
|
49
49
|
val = expr.evaluate(solution, options.merge(
|
50
|
-
:
|
51
|
-
:
|
50
|
+
queryable: queryable,
|
51
|
+
depth: options[:depth].to_i + 1))
|
52
52
|
debug(options) {"===> + #{var} => #{val.inspect}"}
|
53
53
|
solution.bindings[var.to_sym] = val
|
54
54
|
rescue TypeError => e
|
@@ -38,9 +38,9 @@ module SPARQL; module Algebra
|
|
38
38
|
# @see http://www.w3.org/TR/rdf-sparql-query/#ebv
|
39
39
|
def execute(queryable, options = {}, &block)
|
40
40
|
debug(options) {"Filter #{operands.first.to_sxp}"}
|
41
|
-
opts = options.merge(:
|
41
|
+
opts = options.merge(queryable: queryable, depth: options[:depth].to_i + 1)
|
42
42
|
@solutions = RDF::Query::Solutions()
|
43
|
-
queryable.query(operands.last, options.merge(:
|
43
|
+
queryable.query(operands.last, options.merge(depth: options[:depth].to_i + 1)) do |solution|
|
44
44
|
begin
|
45
45
|
pass = boolean(operands.first.evaluate(solution, opts)).true?
|
46
46
|
debug(options) {"(filter) #{pass.inspect} #{solution.to_hash.inspect}"}
|
@@ -4,22 +4,55 @@ module SPARQL; module Algebra
|
|
4
4
|
##
|
5
5
|
# The SPARQL GraphPattern `graph` operator.
|
6
6
|
#
|
7
|
-
# This is a wrapper to add a `context` to the query.
|
7
|
+
# This is a wrapper to add a `context` to the query, or an array of statements.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example of a query
|
10
10
|
# (prefix ((: <http://example/>))
|
11
11
|
# (graph ?g
|
12
12
|
# (bgp (triple ?s ?p ?o))))
|
13
13
|
#
|
14
|
+
# @example named set of statements
|
15
|
+
# (prefix ((: <http://example/>))
|
16
|
+
# (graph :g
|
17
|
+
# ((triple :s :p :o))))
|
18
|
+
#
|
14
19
|
# @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
|
15
20
|
class Graph < Operator::Binary
|
16
21
|
include Query
|
17
22
|
|
18
23
|
NAME = [:graph]
|
24
|
+
##
|
25
|
+
# A `graph` is an RDF::Query with a context. It can also be used as a container of statements or patterns, or other queryable operators (see GraphGraphPattern)
|
26
|
+
#
|
27
|
+
# @overload self.new(name, bgp)
|
28
|
+
# @param [RDF::Resource] name
|
29
|
+
# @param [RDF::Query] patterns
|
30
|
+
# A sub-query (bgp)
|
31
|
+
# @overload self.new(name, bgp)
|
32
|
+
# @param [RDF::Resource] name
|
33
|
+
# @param [Operator] patterns
|
34
|
+
# A sub-query (GraphGraphPattern)
|
35
|
+
# @overload self.new(name, patterns)
|
36
|
+
# @param [RDF::Resource] name
|
37
|
+
# @param [Array<RDF::Query::Pattern>] patterns
|
38
|
+
# Quads
|
39
|
+
# @return [RDF::Query]
|
40
|
+
def self.new(name, patterns, &block)
|
41
|
+
case patterns
|
42
|
+
when RDF::Query
|
43
|
+
# Record that the argument as a (bgp) for re-serialization back to SSE
|
44
|
+
RDF::Query.new(*(patterns.patterns + [{context: name,}]), &block)
|
45
|
+
when Operator
|
46
|
+
super
|
47
|
+
else
|
48
|
+
RDF::Query.new(*(patterns + [{context: name, as_container: true}]), &block)
|
49
|
+
end
|
50
|
+
end
|
19
51
|
|
20
52
|
##
|
21
|
-
#
|
22
|
-
#
|
53
|
+
# If the second operand is a Query operator:
|
54
|
+
# Executes this query on the given `queryable` graph or repository.
|
55
|
+
# Applies the given `context` to the query, limiting the scope of the query to the specified `context`, which may be an `RDF::URI` or `RDF::Query::Variable`.
|
23
56
|
#
|
24
57
|
# @param [RDF::Queryable] queryable
|
25
58
|
# the graph or repository to query
|
@@ -35,7 +68,7 @@ module SPARQL; module Algebra
|
|
35
68
|
def execute(queryable, options = {}, &block)
|
36
69
|
debug(options) {"Graph #{operands.first}"}
|
37
70
|
context, query = operands.first, operands.last
|
38
|
-
@solutions = queryable.query(query, options.merge(:
|
71
|
+
@solutions = queryable.query(query, options.merge(context: context), &block)
|
39
72
|
end
|
40
73
|
|
41
74
|
##
|
@@ -50,6 +83,7 @@ module SPARQL; module Algebra
|
|
50
83
|
|
51
84
|
##
|
52
85
|
# Don't do any more rewriting
|
86
|
+
# FIXME: if ooperator is JOIN, and rewritten sub-operators are queries, can do simple merge of sub-graphs
|
53
87
|
# @return [SPARQL::Algebra::Expression] `self`
|
54
88
|
def rewrite(&block)
|
55
89
|
self
|
@@ -43,7 +43,7 @@ module SPARQL; module Algebra
|
|
43
43
|
exprlist = operands.first
|
44
44
|
query = operands.last
|
45
45
|
aggregates = operands.length == 3 ? operand(1) : []
|
46
|
-
solutions = queryable.query(query, options.merge(:
|
46
|
+
solutions = queryable.query(query, options.merge(depth: options[:depth].to_i + 1))
|
47
47
|
|
48
48
|
groups = solutions.group_by do |solution|
|
49
49
|
# Evaluate each exprlist operand to get groups where each key is a new solution
|
@@ -55,13 +55,13 @@ module SPARQL; module Algebra
|
|
55
55
|
# Form is [variable, expression]
|
56
56
|
soln[operand.first] = operand.last.evaluate(solution,
|
57
57
|
options.merge(
|
58
|
-
:
|
59
|
-
:
|
58
|
+
queryable: queryable,
|
59
|
+
depth: options[:depth].to_i + 1))
|
60
60
|
else
|
61
61
|
# Form is variable
|
62
62
|
soln[operand] = operand.evaluate(solution, options.merge(
|
63
|
-
:
|
64
|
-
:
|
63
|
+
queryable: queryable,
|
64
|
+
depth: options[:depth].to_i + 1))
|
65
65
|
end
|
66
66
|
rescue TypeError
|
67
67
|
# Ignore expression
|
@@ -30,7 +30,7 @@ module SPARQL; module Algebra
|
|
30
30
|
sep = operands.length == 2 ? operand(0).last : RDF::Literal(' ')
|
31
31
|
args_enum = solutions.map do |solution|
|
32
32
|
begin
|
33
|
-
operands.last.evaluate(solution, options.merge(:
|
33
|
+
operands.last.evaluate(solution, options.merge(depth: options[:depth].to_i + 1))
|
34
34
|
rescue TypeError
|
35
35
|
# Ignore errors
|
36
36
|
nil
|
@@ -34,9 +34,9 @@ module SPARQL; module Algebra
|
|
34
34
|
# @return [RDF::Term]
|
35
35
|
# @raise [TypeError]
|
36
36
|
def evaluate(bindings, options = {})
|
37
|
-
operand(0).evaluate(bindings, options.merge(:
|
38
|
-
operand(1).evaluate(bindings, options.merge(:
|
39
|
-
operand(2).evaluate(bindings, options.merge(:
|
37
|
+
operand(0).evaluate(bindings, options.merge(depth: options[:depth].to_i + 1)) == RDF::Literal::TRUE ?
|
38
|
+
operand(1).evaluate(bindings, options.merge(depth: options[:depth].to_i + 1).merge(depth: options[:depth].to_i + 1)) :
|
39
|
+
operand(2).evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))
|
40
40
|
rescue
|
41
41
|
raise TypeError
|
42
42
|
end
|
@@ -45,7 +45,7 @@ module SPARQL; module Algebra
|
|
45
45
|
error_found = false
|
46
46
|
found = operands[1..-1].any? do |op|
|
47
47
|
begin
|
48
|
-
lhs == op.evaluate(bindings, options.merge(:
|
48
|
+
lhs == op.evaluate(bindings, options.merge(depth: options[:depth].to_i + 1))
|
49
49
|
rescue TypeError
|
50
50
|
error_found = true
|
51
51
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
|
4
|
+
##
|
5
|
+
# The SPARQL UPDATE `insertData` operator.
|
6
|
+
#
|
7
|
+
# The INSERT operation is a form of the DELETE/INSERT operation having no DELETE section
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# (insert ((triple ?s ?p "q")))
|
11
|
+
#
|
12
|
+
# @see http://www.w3.org/TR/sparql11-update/#insert
|
13
|
+
class Insert < Operator::Unary
|
14
|
+
include SPARQL::Algebra::Update
|
15
|
+
|
16
|
+
NAME = [:insert]
|
17
|
+
|
18
|
+
##
|
19
|
+
# Executes this upate on the given `writable` graph or repository.
|
20
|
+
#
|
21
|
+
# @param [RDF::Queryable] queryable
|
22
|
+
# the graph or repository to write
|
23
|
+
# @param [RDF::Query::Solution] solution
|
24
|
+
# Solution to map to patterns for this operation
|
25
|
+
# @param [Hash{Symbol => Object}] options
|
26
|
+
# any additional keyword options
|
27
|
+
# @option options [Boolean] debug
|
28
|
+
# Query execution debugging
|
29
|
+
# @return [RDF::Queryable]
|
30
|
+
# Returns queryable.
|
31
|
+
# @raise [IOError]
|
32
|
+
# If `from` does not exist, unless the `silent` operator is present
|
33
|
+
# @see http://www.w3.org/TR/sparql11-update/
|
34
|
+
def execute(queryable, solution, options = {})
|
35
|
+
debug(options) {"Insert"}
|
36
|
+
patterns = operand.inject([]) do |memo, op|
|
37
|
+
if op.respond_to?(:statements)
|
38
|
+
memo += op.statements.to_a
|
39
|
+
else
|
40
|
+
memo << op
|
41
|
+
end
|
42
|
+
memo
|
43
|
+
end
|
44
|
+
patterns.each do |pattern|
|
45
|
+
pattern = pattern.dup.bind(solution)
|
46
|
+
debug(options) {"Insert statement #{statement.to_sse}"}
|
47
|
+
# Only insert bound or constant patterns
|
48
|
+
queryable.insert(RDF::Statement.from(pattern)) if pattern.bound? || pattern.constant?
|
49
|
+
end
|
50
|
+
queryable
|
51
|
+
end
|
52
|
+
end # Insert
|
53
|
+
end # Operator
|
54
|
+
end; end # SPARQL::Algebra
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
|
4
|
+
##
|
5
|
+
# The SPARQL UPDATE `insertData` operator.
|
6
|
+
#
|
7
|
+
# The INSERT DATA operation adds some triples, given inline in the request, into the Graph Store
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# (insertData ((graph <http://example.org/g1> ((triple :s :p :o)))))
|
11
|
+
#
|
12
|
+
# @see http://www.w3.org/TR/sparql11-update/#insertData
|
13
|
+
class InsertData < Operator::Unary
|
14
|
+
include SPARQL::Algebra::Update
|
15
|
+
|
16
|
+
NAME = [:insertData]
|
17
|
+
|
18
|
+
##
|
19
|
+
# Executes this upate on the given `writable` graph or repository.
|
20
|
+
#
|
21
|
+
# @param [RDF::Queryable] queryable
|
22
|
+
# the graph or repository to write
|
23
|
+
# @param [Hash{Symbol => Object}] options
|
24
|
+
# any additional keyword options
|
25
|
+
# @option options [Boolean] debug
|
26
|
+
# Query execution debugging
|
27
|
+
# @return [RDF::Queryable]
|
28
|
+
# Returns queryable.
|
29
|
+
# @raise [IOError]
|
30
|
+
# If `from` does not exist, unless the `silent` operator is present
|
31
|
+
# @see http://www.w3.org/TR/sparql11-update/
|
32
|
+
def execute(queryable, options = {})
|
33
|
+
operand.each do |op|
|
34
|
+
debug(options) {"InsertData #{op.to_sxp}"}
|
35
|
+
queryable.insert(op)
|
36
|
+
end
|
37
|
+
queryable
|
38
|
+
end
|
39
|
+
end # InsertData
|
40
|
+
end # Operator
|
41
|
+
end; end # SPARQL::Algebra
|
@@ -41,10 +41,10 @@ module SPARQL; module Algebra
|
|
41
41
|
# Generate solutions independently, merge based on solution compatibility
|
42
42
|
debug(options) {"Join"}
|
43
43
|
|
44
|
-
left = queryable.query(operand(0), options.merge(:
|
44
|
+
left = queryable.query(operand(0), options.merge(depth: options[:depth].to_i + 1))
|
45
45
|
debug(options) {"(join)=>(left) #{left.inspect}"}
|
46
46
|
|
47
|
-
right = queryable.query(operand(1), options.merge(:
|
47
|
+
right = queryable.query(operand(1), options.merge(depth: options[:depth].to_i + 1))
|
48
48
|
debug(options) {"(join)=>(right) #{right.inspect}"}
|
49
49
|
|
50
50
|
@solutions = RDF::Query::Solutions(left.map do |s1|
|
@@ -22,7 +22,7 @@ module SPARQL; module Algebra
|
|
22
22
|
# @raise [TypeError] if the operand is not a literal value
|
23
23
|
def apply(operand)
|
24
24
|
case operand
|
25
|
-
when RDF::Literal then RDF::Literal(operand.to_s.downcase, :
|
25
|
+
when RDF::Literal then RDF::Literal(operand.to_s.downcase, datatype: operand.datatype, language: operand.language)
|
26
26
|
else raise TypeError, "expected an RDF::Literal::Numeric, but got #{operand.inspect}"
|
27
27
|
end
|
28
28
|
end
|
@@ -38,10 +38,10 @@ module SPARQL; module Algebra
|
|
38
38
|
filter = operand(2)
|
39
39
|
|
40
40
|
debug(options) {"LeftJoin"}
|
41
|
-
left = queryable.query(operand(0), options.merge(:
|
41
|
+
left = queryable.query(operand(0), options.merge(depth: options[:depth].to_i + 1))
|
42
42
|
debug(options) {"=>(leftjoin left) #{left.inspect}"}
|
43
43
|
|
44
|
-
right = queryable.query(operand(1), options.merge(:
|
44
|
+
right = queryable.query(operand(1), options.merge(depth: options[:depth].to_i + 1))
|
45
45
|
debug(options) {"=>(leftjoin right) #{right.inspect}"}
|
46
46
|
|
47
47
|
# LeftJoin(Ω1, Ω2, expr) =
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
|
4
|
+
##
|
5
|
+
# The SPARQL UPDATE `load` operator.
|
6
|
+
#
|
7
|
+
# The LOAD operation reads an RDF document from a IRI and inserts its triples into the specified graph in the Graph Store. The specified destination graph should be created if required; again, implementations providing an update service over a fixed set of graphs must return with failure for a request that would create a disallowed graph. If the destination graph already exists, then no data in that graph will be removed.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# (load <remote> <g>)
|
11
|
+
#
|
12
|
+
# @see http://www.w3.org/TR/sparql11-update/#load
|
13
|
+
class Load < Operator
|
14
|
+
include SPARQL::Algebra::Update
|
15
|
+
|
16
|
+
NAME = [:load]
|
17
|
+
|
18
|
+
##
|
19
|
+
# Executes this upate on the given `writable` graph or repository.
|
20
|
+
#
|
21
|
+
# @param [RDF::Queryable] queryable
|
22
|
+
# the graph or repository to write
|
23
|
+
# @param [Hash{Symbol => Object}] options
|
24
|
+
# any additional keyword options
|
25
|
+
# @option options [Boolean] debug
|
26
|
+
# Query execution debugging
|
27
|
+
# @return [RDF::Queryable]
|
28
|
+
# Returns queryable.
|
29
|
+
# @raise [IOError]
|
30
|
+
# If `from` does not exist, unless the `silent` operator is present
|
31
|
+
# @see http://www.w3.org/TR/sparql11-update/
|
32
|
+
def execute(queryable, options = {})
|
33
|
+
debug(options) {"Load"}
|
34
|
+
silent = operands.first == :silent
|
35
|
+
operands.shift if silent
|
36
|
+
|
37
|
+
raise ArgumentError, "load expected one or two operands, got #{operands.length}" unless [1,2].include?(operands.length)
|
38
|
+
|
39
|
+
location, name = operands
|
40
|
+
queryable.load(location, context: name)
|
41
|
+
rescue IOError, Errno::ENOENT
|
42
|
+
raise unless silent
|
43
|
+
ensure
|
44
|
+
queryable
|
45
|
+
end
|
46
|
+
end # Load
|
47
|
+
end # Operator
|
48
|
+
end; end # SPARQL::Algebra
|
@@ -42,9 +42,9 @@ module SPARQL; module Algebra
|
|
42
42
|
#
|
43
43
|
# card[Minus(Ω1, Ω2)](μ) = card[Ω1](μ)
|
44
44
|
debug(options) {"Minus"}
|
45
|
-
left = queryable.query(operand(0), options.merge(:
|
45
|
+
left = queryable.query(operand(0), options.merge(depth: options[:depth].to_i + 1))
|
46
46
|
debug(options) {"(minus left) #{left.inspect}"}
|
47
|
-
right = queryable.query(operand(1), options.merge(:
|
47
|
+
right = queryable.query(operand(1), options.merge(depth: options[:depth].to_i + 1))
|
48
48
|
debug(options) {"(minus right) #{right.inspect}"}
|
49
49
|
@solutions = left.minus(right)
|
50
50
|
@solutions.each(&block) if block_given?
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module SPARQL; module Algebra
|
2
|
+
class Operator
|
3
|
+
|
4
|
+
##
|
5
|
+
# The SPARQL UPDATE `modify` operator.
|
6
|
+
#
|
7
|
+
# Wraps delete/insert
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# (modify
|
11
|
+
# (bgp (triple ?a foaf:knows ?b))
|
12
|
+
# (delete ((triple ?a foaf:knows ?b)))
|
13
|
+
# (insert ((triple ?b foaf:knows ?a)))
|
14
|
+
#
|
15
|
+
# @see XXX
|
16
|
+
class Modify < Operator
|
17
|
+
include SPARQL::Algebra::Update
|
18
|
+
|
19
|
+
NAME = [:modify]
|
20
|
+
|
21
|
+
##
|
22
|
+
# Executes this upate on the given `writable` graph or repository.
|
23
|
+
#
|
24
|
+
# Execute the first operand to get solutions, and apply those solutions to the subsequent operators.
|
25
|
+
#
|
26
|
+
# @param [RDF::Queryable] queryable
|
27
|
+
# the graph or repository to write
|
28
|
+
# @param [Hash{Symbol => Object}] options
|
29
|
+
# any additional keyword options
|
30
|
+
# @option options [Boolean] debug
|
31
|
+
# Query execution debugging
|
32
|
+
# @return [RDF::Queryable]
|
33
|
+
# Returns queryable.
|
34
|
+
# @raise [IOError]
|
35
|
+
# If `from` does not exist, unless the `silent` operator is present
|
36
|
+
# @see http://www.w3.org/TR/sparql11-update/
|
37
|
+
def execute(queryable, options = {})
|
38
|
+
debug(options) {"Modify"}
|
39
|
+
query = operands.shift
|
40
|
+
|
41
|
+
queryable.query(query, options.merge(depth: options[:depth].to_i + 1)) do |solution|
|
42
|
+
debug(options) {"(solution)=>#{solution.inspect}"}
|
43
|
+
|
44
|
+
# Execute each operand with queryable and solution
|
45
|
+
operands.each do |op|
|
46
|
+
op.execute(queryable, solution, options.merge(depth: options[:depth].to_i + 1))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
queryable
|
50
|
+
end
|
51
|
+
end # Modify
|
52
|
+
end # Operator
|
53
|
+
end; end # SPARQL::Algebra
|