sparql 1.1.1 → 1.1.2

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -4
  3. data/VERSION +1 -1
  4. data/lib/rack/sparql/conneg.rb +5 -2
  5. data/lib/sinatra/sparql.rb +9 -16
  6. data/lib/sinatra/sparql/extensions.rb +0 -2
  7. data/lib/sparql.rb +8 -5
  8. data/lib/sparql/algebra/expression.rb +1 -1
  9. data/lib/sparql/algebra/extensions.rb +34 -6
  10. data/lib/sparql/algebra/operator/ask.rb +13 -5
  11. data/lib/sparql/algebra/operator/base.rb +19 -5
  12. data/lib/sparql/algebra/operator/bgp.rb +6 -2
  13. data/lib/sparql/algebra/operator/construct.rb +19 -8
  14. data/lib/sparql/algebra/operator/dataset.rb +8 -4
  15. data/lib/sparql/algebra/operator/datatype.rb +1 -7
  16. data/lib/sparql/algebra/operator/describe.rb +16 -6
  17. data/lib/sparql/algebra/operator/distinct.rb +7 -6
  18. data/lib/sparql/algebra/operator/exists.rb +3 -6
  19. data/lib/sparql/algebra/operator/extend.rb +11 -1
  20. data/lib/sparql/algebra/operator/filter.rb +12 -17
  21. data/lib/sparql/algebra/operator/graph.rb +6 -4
  22. data/lib/sparql/algebra/operator/group.rb +10 -5
  23. data/lib/sparql/algebra/operator/join.rb +16 -9
  24. data/lib/sparql/algebra/operator/left_join.rb +15 -11
  25. data/lib/sparql/algebra/operator/minus.rb +11 -7
  26. data/lib/sparql/algebra/operator/notexists.rb +1 -1
  27. data/lib/sparql/algebra/operator/order.rb +9 -3
  28. data/lib/sparql/algebra/operator/prefix.rb +19 -2
  29. data/lib/sparql/algebra/operator/project.rb +9 -4
  30. data/lib/sparql/algebra/operator/reduced.rb +8 -3
  31. data/lib/sparql/algebra/operator/slice.rb +8 -1
  32. data/lib/sparql/algebra/operator/table.rb +7 -2
  33. data/lib/sparql/algebra/operator/union.rb +7 -2
  34. data/lib/sparql/algebra/query.rb +26 -6
  35. data/lib/sparql/extensions.rb +0 -8
  36. data/lib/sparql/grammar/parser11.rb +1 -1
  37. data/lib/sparql/results.rb +6 -4
  38. metadata +25 -25
@@ -29,13 +29,7 @@ module SPARQL; module Algebra
29
29
  # @raise [TypeError] if the operand is not a typed or simple literal
30
30
  def apply(literal)
31
31
  case literal
32
- when RDF::Literal then case
33
- when RDF::VERSION.to_s >= "1.1" then literal.datatype
34
- when literal.simple? then RDF::XSD.string
35
- when literal.datatype == RDF::XSD.string then RDF::XSD.string
36
- when literal.plain? then RDF.langString
37
- else RDF::URI(literal.datatype)
38
- end
32
+ when RDF::Literal then literal.datatype
39
33
  else raise TypeError, "expected an RDF::Literal, but got #{literal.inspect}"
40
34
  end
41
35
  end
@@ -33,10 +33,14 @@ module SPARQL; module Algebra
33
33
  # the graph or repository to query
34
34
  # @param [Hash{Symbol => Object}] options
35
35
  # any additional keyword options
36
- # @return [RDF::Query::Solutions]
37
- # the resulting solution sequence
36
+ # @yield [statement]
37
+ # each matching statement
38
+ # @yieldparam [RDF::Statement] solution
39
+ # @yieldreturn [void] ignored
40
+ # @return [RDF::Graph]
41
+ # containing the constructed triples
38
42
  # @see http://www.w3.org/TR/rdf-sparql-query/#describe
39
- def execute(queryable, options = {})
43
+ def execute(queryable, options = {}, &block)
40
44
  debug(options) {"Describe #{operands.first}, #{options.inspect}"}
41
45
 
42
46
  # Describe any constand URIs
@@ -44,17 +48,17 @@ module SPARQL; module Algebra
44
48
 
45
49
  to_describe.each {|t| debug(options) {"=> describe #{t}"}}
46
50
 
47
- operands.last.execute(queryable).each do |solution|
51
+ queryable.query(operands.last) do |solution|
48
52
  solution.each_variable do |v|
49
53
  if operands.first.any? {|bound| v.eql?(bound)}
50
- debug(options) {"=> describe #{v}"}
54
+ debug(options) {"(describe)=> #{v}"}
51
55
  to_describe << v.value
52
56
  end
53
57
  end
54
58
  end
55
59
 
56
60
  # Return Concise Bounded Description
57
- queryable.concise_bounded_description(*to_describe)
61
+ queryable.concise_bounded_description(*to_describe.uniq, &block)
58
62
  end
59
63
 
60
64
  ##
@@ -66,6 +70,12 @@ module SPARQL; module Algebra
66
70
  def optimize
67
71
  operands = operands.map(&:optimize)
68
72
  end
73
+
74
+ # Query results statements (e.g., CONSTRUCT, DESCRIBE, CREATE)
75
+ # @return [Boolean]
76
+ def query_yields_statements?
77
+ true
78
+ end
69
79
  end # Construct
70
80
  end # Operator
71
81
  end; end # SPARQL::Algebra
@@ -24,15 +24,16 @@ module SPARQL; module Algebra
24
24
  # the graph or repository to query
25
25
  # @param [Hash{Symbol => Object}] options
26
26
  # any additional keyword options
27
+ # @yield [solution]
28
+ # each matching solution
29
+ # @yieldparam [RDF::Query::Solution] solution
30
+ # @yieldreturn [void] ignored
27
31
  # @return [RDF::Query::Solutions]
28
32
  # the resulting solution sequence
29
33
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
30
- def execute(queryable, options = {})
31
- debug(options) {"Distinct"}
32
- @solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
33
- debug(options) {"=>(before) #{@solutions.inspect}"}
34
- @solutions = @solutions.distinct
35
- debug(options) {"=>(after) #{@solutions.inspect}"}
34
+ def execute(queryable, options = {}, &block)
35
+ @solutions = queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1)).distinct
36
+ @solutions.each(&block) if block_given?
36
37
  @solutions
37
38
  end
38
39
 
@@ -5,10 +5,8 @@ module SPARQL; module Algebra
5
5
  #
6
6
  # @example
7
7
  # (prefix ((ex: <http://www.example.org/>))
8
- # (filter (exists
9
- # (filter (notexists (bgp (triple ?s ?p ex:o2)))
10
- # (bgp (triple ?s ?p ex:o1))))
11
- # (bgp (triple ?s ?p ex:o))))
8
+ # (filter (exists (bgp (triple ?s ?p ex:o)))
9
+ # (bgp (triple ?s ?p ?o))))
12
10
  #
13
11
  # @see http://www.w3.org/TR/sparql11-query/#func-abs
14
12
  # @see http://www.w3.org/TR/xpath-functions/#func-abs
@@ -28,10 +26,9 @@ module SPARQL; module Algebra
28
26
  # queryable to execute, using bindings as an initial solution.
29
27
  # @return [RDF::Literal::Boolean] `true` or `false`
30
28
  def evaluate(bindings, options = {})
31
- solutions = RDF::Query::Solutions.new << bindings
32
29
  queryable = options[:queryable]
33
30
  !operand(0).execute(queryable, options.merge(
34
- :solutions => solutions,
31
+ :solutions => RDF::Query::Solutions(bindings),
35
32
  :depth => options[:depth].to_i + 1)).empty?
36
33
  end
37
34
  end # Exists
@@ -27,10 +27,19 @@ module SPARQL; module Algebra
27
27
  # Extend is undefined when var in dom(μ).
28
28
  #
29
29
  # Extend(Ω, var, expr) = { Extend(μ, var, expr) | μ in Ω }
30
+ #
31
+ # @param [RDF::Queryable] queryable
32
+ # the graph or repository to query
33
+ # @param [Hash{Symbol => Object}] options
34
+ # any additional keyword options
35
+ # @yield [solution]
36
+ # each matching solution
37
+ # @yieldparam [RDF::Query::Solution] solution
38
+ # @yieldreturn [void] ignored
30
39
  # @return [RDF::Query::Solutions]
31
40
  # the resulting solution sequence
32
41
  # @see http://www.w3.org/TR/rdf-sparql-query/#evaluation
33
- def execute(queryable, options = {})
42
+ def execute(queryable, options = {}, &block)
34
43
  debug(options) {"Extend"}
35
44
  @solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
36
45
  @solutions.each do |solution|
@@ -48,6 +57,7 @@ module SPARQL; module Algebra
48
57
  end
49
58
  end
50
59
  end
60
+ @solutions.each(&block) if block_given?
51
61
  @solutions
52
62
  end
53
63
 
@@ -28,33 +28,28 @@ module SPARQL; module Algebra
28
28
  # the graph or repository to query
29
29
  # @param [Hash{Symbol => Object}] options
30
30
  # any additional keyword options
31
+ # @yield [solution]
32
+ # each matching solution
33
+ # @yieldparam [RDF::Query::Solution] solution
34
+ # @yieldreturn [void] ignored
31
35
  # @return [RDF::Query::Solutions]
32
36
  # the resulting solution sequence
33
37
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
34
38
  # @see http://www.w3.org/TR/rdf-sparql-query/#ebv
35
- def execute(queryable, options = {})
39
+ def execute(queryable, options = {}, &block)
36
40
  debug(options) {"Filter #{operands.first.to_sxp}"}
37
- @solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
38
- debug(options) {"=>(before) #{@solutions.map(&:to_hash).inspect}"}
39
41
  opts = options.merge(:queryable => queryable, :depth => options[:depth].to_i + 1)
40
- @solutions = @solutions.filter do |solution|
41
- # Evaluate the solution, which will return true or false
42
- #debug(options) {"===>(evaluate) #{operands.first.inspect} against #{solution.to_hash.inspect}"}
43
-
44
- # From http://www.w3.org/TR/rdf-sparql-query/#tests
45
- # FILTERs eliminate any solutions that, when substituted into the expression, either
46
- # result in an effective boolean value of false or produce an error.
42
+ @solutions = RDF::Query::Solutions()
43
+ queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1)) do |solution|
47
44
  begin
48
- res = boolean(operands.first.evaluate(solution, opts)).true?
49
- debug(options) {"===>#{res} #{solution.to_hash.inspect}"}
50
- res
45
+ pass = boolean(operands.first.evaluate(solution, opts)).true?
46
+ debug(options) {"(filter) #{pass.inspect} #{solution.to_hash.inspect}"}
47
+ @solutions << solution if pass
51
48
  rescue
52
- debug(options) {"rescue(#{$!}): #{solution.to_hash.inspect}"}
53
- false
49
+ debug(options) {"(filter) rescue(#{$!}): #{solution.to_hash.inspect}"}
54
50
  end
55
51
  end
56
- @solutions = RDF::Query::Solutions.new(@solutions)
57
- debug(options) {"=>(after) #{@solutions.map(&:to_hash).inspect}"}
52
+ @solutions.each(&block) if block_given?
58
53
  @solutions
59
54
  end
60
55
 
@@ -25,15 +25,17 @@ module SPARQL; module Algebra
25
25
  # the graph or repository to query
26
26
  # @param [Hash{Symbol => Object}] options
27
27
  # any additional keyword options
28
+ # @yield [solution]
29
+ # each matching solution
30
+ # @yieldparam [RDF::Query::Solution] solution
31
+ # @yieldreturn [void] ignored
28
32
  # @return [RDF::Query::Solutions]
29
33
  # the resulting solution sequence
30
34
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
31
- def execute(queryable, options = {})
35
+ def execute(queryable, options = {}, &block)
32
36
  debug(options) {"Graph #{operands.first}"}
33
37
  context, query = operands.first, operands.last
34
- @solutions = query.execute(queryable, options.merge(:context => context))
35
- debug(options) {"=>(after) #{@solutions.map(&:to_hash).inspect}"}
36
- @solutions
38
+ @solutions = queryable.query(query, options.merge(:context => context), &block)
37
39
  end
38
40
 
39
41
  ##
@@ -31,15 +31,19 @@ module SPARQL; module Algebra
31
31
  # the graph or repository to query
32
32
  # @param [Hash{Symbol => Object}] options
33
33
  # any additional keyword options
34
+ # @yield [solution]
35
+ # each matching solution
36
+ # @yieldparam [RDF::Query::Solution] solution
37
+ # @yieldreturn [void] ignored
34
38
  # @return [RDF::Query::Solutions]
35
39
  # the resulting solution sequence
36
40
  # @see http://www.w3.org/TR/sparql11-query/#sparqlGroupAggregate
37
- def execute(queryable, options = {})
41
+ def execute(queryable, options = {}, &block)
38
42
  debug(options) {"Group"}
39
43
  exprlist = operands.first
40
44
  query = operands.last
41
45
  aggregates = operands.length == 3 ? operand(1) : []
42
- solutions = query.execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
46
+ solutions = queryable.query(query, options.merge(:depth => options[:depth].to_i + 1))
43
47
 
44
48
  groups = solutions.group_by do |solution|
45
49
  # Evaluate each exprlist operand to get groups where each key is a new solution
@@ -69,7 +73,7 @@ module SPARQL; module Algebra
69
73
  debug(options) {"=>(groups) #{groups.inspect}"}
70
74
 
71
75
  # Aggregate solutions in each group using aggregates to get solutions
72
- @solutions = groups.map do |group_soln, solns|
76
+ @solutions = RDF::Query::Solutions(groups.map do |group_soln, solns|
73
77
  aggregates.each do |(var, aggregate)|
74
78
  begin
75
79
  group_soln[var] = aggregate.aggregate(solns, options)
@@ -78,13 +82,14 @@ module SPARQL; module Algebra
78
82
  end
79
83
  end
80
84
  group_soln
81
- end
85
+ end)
82
86
 
83
87
  # Make sure that's at least an empty solution
84
88
  @solutions << RDF::Query::Solution.new if @solutions.empty?
85
89
 
86
90
  debug(options) {"=>(solutions) #{@solutions.inspect}"}
87
- @solutions = RDF::Query::Solutions.new(@solutions)
91
+ @solutions.each(&block) if block_given?
92
+ @solutions
88
93
  end
89
94
 
90
95
  ##
@@ -25,26 +25,33 @@ module SPARQL; module Algebra
25
25
  # the graph or repository to query
26
26
  # @param [Hash{Symbol => Object}] options
27
27
  # any additional keyword options
28
+ # @yield [solution]
29
+ # each matching solution
30
+ # @yieldparam [RDF::Query::Solution] solution
31
+ # @yieldreturn [void] ignored
28
32
  # @return [RDF::Query::Solutions]
29
33
  # the resulting solution sequence
30
34
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
31
35
  # @see http://rdf.rubyforge.org/RDF/Query/Solution.html#merge-instance_method
32
36
  # @see http://rdf.rubyforge.org/RDF/Query/Solution.html#compatible%3F-instance_method
33
- def execute(queryable, options = {})
37
+ def execute(queryable, options = {}, &block)
34
38
  # Join(Ω1, Ω2) = { merge(μ1, μ2) | μ1 in Ω1 and μ2 in Ω2, and μ1 and μ2 are compatible }
35
39
  # eval(D(G), Join(P1, P2)) = Join(eval(D(G), P1), eval(D(G), P2))
36
40
  #
37
41
  # Generate solutions independently, merge based on solution compatibility
38
42
  debug(options) {"Join"}
39
- solutions1 = operand(0).execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
40
- debug(options) {"=>(left) #{solutions1.inspect}"}
41
- solutions2 = operand(1).execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
42
- debug(options) {"=>(right) #{solutions2.inspect}"}
43
- @solutions = solutions1.map do |s1|
44
- solutions2.map { |s2| s2.merge(s1) if s2.compatible?(s1) }
45
- end.flatten.compact
46
- @solutions = RDF::Query::Solutions.new(@solutions)
43
+
44
+ left = queryable.query(operand(0), options.merge(:depth => options[:depth].to_i + 1))
45
+ debug(options) {"(join)=>(left) #{left.inspect}"}
46
+
47
+ right = queryable.query(operand(1), options.merge(:depth => options[:depth].to_i + 1))
48
+ debug(options) {"(join)=>(right) #{right.inspect}"}
49
+
50
+ @solutions = RDF::Query::Solutions(left.map do |s1|
51
+ right.map { |s2| s2.merge(s1) if s2.compatible?(s1) }
52
+ end.flatten.compact)
47
53
  debug(options) {"=> #{@solutions.inspect}"}
54
+ @solutions.each(&block) if block_given?
48
55
  @solutions
49
56
  end
50
57
 
@@ -25,23 +25,27 @@ module SPARQL; module Algebra
25
25
  # the graph or repository to query
26
26
  # @param [Hash{Symbol => Object}] options
27
27
  # any additional keyword options
28
+ # @yield [solution]
29
+ # each matching solution
30
+ # @yieldparam [RDF::Query::Solution] solution
31
+ # @yieldreturn [void] ignored
28
32
  # @return [RDF::Query::Solutions]
29
33
  # the resulting solution sequence
30
34
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
31
35
  # @see http://rdf.rubyforge.org/RDF/Query/Solution.html#merge-instance_method
32
36
  # @see http://rdf.rubyforge.org/RDF/Query/Solution.html#compatible%3F-instance_method
33
- def execute(queryable, options = {})
37
+ def execute(queryable, options = {}, &block)
34
38
  filter = operand(2)
35
39
 
36
-
37
40
  debug(options) {"LeftJoin"}
38
- left = operand(0).execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
39
- debug(options) {"=>(left) #{left.inspect}"}
40
- right = operand(1).execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
41
- debug(options) {"=>(right) #{right.inspect}"}
42
-
41
+ left = queryable.query(operand(0), options.merge(:depth => options[:depth].to_i + 1))
42
+ debug(options) {"=>(leftjoin left) #{left.inspect}"}
43
+
44
+ right = queryable.query(operand(1), options.merge(:depth => options[:depth].to_i + 1))
45
+ debug(options) {"=>(leftjoin right) #{right.inspect}"}
46
+
43
47
  # LeftJoin(Ω1, Ω2, expr) =
44
- solutions = []
48
+ @solutions = RDF::Query::Solutions()
45
49
  left.each do |s1|
46
50
  load_left = true
47
51
  right.each do |s2|
@@ -52,18 +56,18 @@ module SPARQL; module Algebra
52
56
  if expr && s1.compatible?(s2)
53
57
  # { merge(μ1, μ2) | μ1 in Ω1 and μ2 in Ω2, and μ1 and μ2 are compatible and expr(merge(μ1, μ2)) is true }
54
58
  debug(options) {"=>(merge s1 s2) #{s.inspect}"}
55
- solutions << s
59
+ @solutions << s
56
60
  load_left = false # Left solution added one or more times due to merge
57
61
  end
58
62
  end
59
63
  if load_left
60
64
  debug(options) {"=>(add) #{s1.inspect}"}
61
- solutions << s1
65
+ @solutions << s1
62
66
  end
63
67
  end
64
68
 
65
- @solutions = RDF::Query::Solutions.new(solutions)
66
69
  debug(options) {"=> #{@solutions.inspect}"}
70
+ @solutions.each(&block) if block_given?
67
71
  @solutions
68
72
  end
69
73
 
@@ -27,23 +27,27 @@ module SPARQL; module Algebra
27
27
  # the graph or repository to query
28
28
  # @param [Hash{Symbol => Object}] options
29
29
  # any additional keyword options
30
+ # @yield [solution]
31
+ # each matching solution
32
+ # @yieldparam [RDF::Query::Solution] solution
33
+ # @yieldreturn [void] ignored
30
34
  # @return [RDF::Query::Solutions]
31
35
  # the resulting solution sequence
32
36
  # @see http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#defn_algMinus
33
37
  # @see http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#negation
34
- def execute(queryable, options = {})
38
+ def execute(queryable, options = {}, &block)
35
39
  # Let Ω1 and Ω2 be multisets of solution mappings. We define:
36
40
  #
37
41
  # Minus(Ω1, Ω2) = { μ | μ in Ω1 . ∀ μ' in Ω2, either μ and μ' are not compatible or dom(μ) and dom(μ') are disjoint }
38
42
  #
39
43
  # card[Minus(Ω1, Ω2)](μ) = card[Ω1](μ)
40
44
  debug(options) {"Minus"}
41
- solutions1 = operand(0).execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
42
- debug(options) {"=>(left) #{solutions1.inspect}"}
43
- solutions2 = operand(1).execute(queryable, options.merge(:depth => options[:depth].to_i + 1)) || {}
44
- debug(options) {"=>(right) #{solutions2.inspect}"}
45
- @solutions = solutions1.minus(solutions2)
46
- debug(options) {"=> #{@solutions.inspect}"}
45
+ left = queryable.query(operand(0), options.merge(:depth => options[:depth].to_i + 1))
46
+ debug(options) {"(minus left) #{left.inspect}"}
47
+ right = queryable.query(operand(1), options.merge(:depth => options[:depth].to_i + 1))
48
+ debug(options) {"(minus right) #{right.inspect}"}
49
+ @solutions = left.minus(right)
50
+ @solutions.each(&block) if block_given?
47
51
  @solutions
48
52
  end
49
53
 
@@ -28,7 +28,7 @@ module SPARQL; module Algebra
28
28
  # queryable to execute, using bindings as an initial solution.
29
29
  # @return [RDF::Literal::Boolean] `true` or `false`
30
30
  def evaluate(bindings, options = {})
31
- solutions = RDF::Query::Solutions.new << bindings
31
+ solutions = RDF::Query::Solutions(bindings)
32
32
  queryable = options[:queryable]
33
33
  operand(0).execute(queryable, options.merge(:solutions => solutions)).empty?
34
34
  end
@@ -24,14 +24,18 @@ module SPARQL; module Algebra
24
24
  # the graph or repository to query
25
25
  # @param [Hash{Symbol => Object}] options
26
26
  # any additional keyword options
27
+ # @yield [solution]
28
+ # each matching solution
29
+ # @yieldparam [RDF::Query::Solution] solution
30
+ # @yieldreturn [void] ignored
27
31
  # @return [RDF::Query::Solutions]
28
32
  # the resulting solution sequence
29
33
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
30
- def execute(queryable, options = {})
34
+ def execute(queryable, options = {}, &block)
31
35
  debug(options) {"Order"}
32
- @solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1)).order do |a, b|
36
+ @solutions = queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1)).order do |a, b|
33
37
  operand(0).inject(false) do |memo, op|
34
- debug(options) {"=> #{op.inspect}"}
38
+ debug(options) {"(order) #{op.inspect}"}
35
39
  memo ||= begin
36
40
  a_eval = op.evaluate(a, options.merge(:queryable => queryable, :depth => options[:depth].to_i + 1)) rescue nil
37
41
  b_eval = op.evaluate(b, options.merge(:queryable => queryable, :depth => options[:depth].to_i + 1)) rescue nil
@@ -49,6 +53,8 @@ module SPARQL; module Algebra
49
53
  end
50
54
  end || 0 # They compare equivalently if there are no matches
51
55
  end
56
+ @solutions.each(&block) if block_given?
57
+ @solutions
52
58
  end
53
59
 
54
60
  ##
@@ -23,11 +23,16 @@ module SPARQL; module Algebra
23
23
  # the graph or repository to query
24
24
  # @param [Hash{Symbol => Object}] options
25
25
  # any additional keyword options
26
+ # @yield [solution]
27
+ # each matching solution, statement or boolean
28
+ # @yieldparam [RDF::Statement, RDF::Query::Solution, Boolean] solution
29
+ # @yieldreturn [void] ignored
26
30
  # @return [RDF::Query::Solutions]
27
31
  # the resulting solution sequence
28
32
  # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
29
- def execute(queryable, options = {})
30
- @solutions = operands.last.execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
33
+ def execute(queryable, options = {}, &block)
34
+ debug(options) {"Prefix"}
35
+ @solutions = queryable.query(operands.last, options.merge(:depth => options[:depth].to_i + 1), &block)
31
36
  end
32
37
 
33
38
  ##
@@ -48,6 +53,18 @@ module SPARQL; module Algebra
48
53
  operands[0] += other.operands[0]
49
54
  self
50
55
  end
56
+
57
+ # Query results in a boolean result (e.g., ASK)
58
+ # @return [Boolean]
59
+ def query_yields_boolean?
60
+ operands.last.query_yields_boolean?
61
+ end
62
+
63
+ # Query results statements (e.g., CONSTRUCT, DESCRIBE, CREATE)
64
+ # @return [Boolean]
65
+ def query_yields_statements?
66
+ operands.last.query_yields_statements?
67
+ end
51
68
  end # Prefix
52
69
  end # Operator
53
70
  end; end # SPARQL::Algebra