sparql 0.0.1 → 0.0.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.
- data/AUTHORS +3 -0
 - data/CREDITS +0 -0
 - data/README.markdown +103 -53
 - data/UNLICENSE +24 -0
 - data/VERSION +1 -0
 - data/bin/sparql +87 -0
 - data/lib/sparql.rb +105 -22
 - data/lib/sparql/algebra.rb +369 -0
 - data/lib/sparql/algebra/evaluatable.rb +37 -0
 - data/lib/sparql/algebra/expression.rb +284 -0
 - data/lib/sparql/algebra/extensions.rb +159 -0
 - data/lib/sparql/algebra/operator.rb +492 -0
 - data/lib/sparql/algebra/operator/add.rb +34 -0
 - data/lib/sparql/algebra/operator/and.rb +65 -0
 - data/lib/sparql/algebra/operator/asc.rb +29 -0
 - data/lib/sparql/algebra/operator/ask.rb +46 -0
 - data/lib/sparql/algebra/operator/base.rb +46 -0
 - data/lib/sparql/algebra/operator/bgp.rb +26 -0
 - data/lib/sparql/algebra/operator/bound.rb +48 -0
 - data/lib/sparql/algebra/operator/compare.rb +84 -0
 - data/lib/sparql/algebra/operator/construct.rb +85 -0
 - data/lib/sparql/algebra/operator/dataset.rb +77 -0
 - data/lib/sparql/algebra/operator/datatype.rb +42 -0
 - data/lib/sparql/algebra/operator/desc.rb +17 -0
 - data/lib/sparql/algebra/operator/describe.rb +71 -0
 - data/lib/sparql/algebra/operator/distinct.rb +50 -0
 - data/lib/sparql/algebra/operator/divide.rb +43 -0
 - data/lib/sparql/algebra/operator/equal.rb +32 -0
 - data/lib/sparql/algebra/operator/exprlist.rb +52 -0
 - data/lib/sparql/algebra/operator/filter.rb +71 -0
 - data/lib/sparql/algebra/operator/graph.rb +28 -0
 - data/lib/sparql/algebra/operator/greater_than.rb +32 -0
 - data/lib/sparql/algebra/operator/greater_than_or_equal.rb +33 -0
 - data/lib/sparql/algebra/operator/is_blank.rb +35 -0
 - data/lib/sparql/algebra/operator/is_iri.rb +37 -0
 - data/lib/sparql/algebra/operator/is_literal.rb +36 -0
 - data/lib/sparql/algebra/operator/join.rb +67 -0
 - data/lib/sparql/algebra/operator/lang.rb +29 -0
 - data/lib/sparql/algebra/operator/lang_matches.rb +53 -0
 - data/lib/sparql/algebra/operator/left_join.rb +95 -0
 - data/lib/sparql/algebra/operator/less_than.rb +32 -0
 - data/lib/sparql/algebra/operator/less_than_or_equal.rb +32 -0
 - data/lib/sparql/algebra/operator/minus.rb +31 -0
 - data/lib/sparql/algebra/operator/multiply.rb +34 -0
 - data/lib/sparql/algebra/operator/not.rb +35 -0
 - data/lib/sparql/algebra/operator/not_equal.rb +26 -0
 - data/lib/sparql/algebra/operator/or.rb +65 -0
 - data/lib/sparql/algebra/operator/order.rb +69 -0
 - data/lib/sparql/algebra/operator/plus.rb +31 -0
 - data/lib/sparql/algebra/operator/prefix.rb +45 -0
 - data/lib/sparql/algebra/operator/project.rb +46 -0
 - data/lib/sparql/algebra/operator/reduced.rb +47 -0
 - data/lib/sparql/algebra/operator/regex.rb +70 -0
 - data/lib/sparql/algebra/operator/same_term.rb +46 -0
 - data/lib/sparql/algebra/operator/slice.rb +60 -0
 - data/lib/sparql/algebra/operator/str.rb +35 -0
 - data/lib/sparql/algebra/operator/subtract.rb +32 -0
 - data/lib/sparql/algebra/operator/union.rb +55 -0
 - data/lib/sparql/algebra/query.rb +99 -0
 - data/lib/sparql/algebra/sxp_extensions.rb +35 -0
 - data/lib/sparql/algebra/version.rb +20 -0
 - data/lib/sparql/extensions.rb +102 -0
 - data/lib/sparql/grammar.rb +298 -0
 - data/lib/sparql/grammar/lexer.rb +609 -0
 - data/lib/sparql/grammar/parser.rb +1383 -0
 - data/lib/sparql/grammar/parser/meta.rb +1801 -0
 - data/lib/sparql/results.rb +220 -0
 - data/lib/sparql/version.rb +20 -0
 - metadata +232 -62
 - data/Rakefile +0 -22
 - data/coverage/index.html +0 -252
 - data/coverage/lib-sparql-execute_sparql_rb.html +0 -621
 - data/coverage/lib-sparql_rb.html +0 -622
 - data/lib/sparql/execute_sparql.rb +0 -27
 - data/lib/sparql/sparql.treetop +0 -159
 - data/sparql.gemspec +0 -16
 - data/spec/spec.opts +0 -2
 - data/spec/spec_helper.rb +0 -24
 - data/spec/unit/graph_parsing_spec.rb +0 -76
 - data/spec/unit/iri_parsing_spec.rb +0 -46
 - data/spec/unit/prefixed_names_parsing_spec.rb +0 -40
 - data/spec/unit/primitives_parsing_spec.rb +0 -26
 - data/spec/unit/sparql_parsing_spec.rb +0 -72
 - data/spec/unit/variables_parsing_spec.rb +0 -36
 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL GraphPattern `reduced` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
         
     | 
| 
      
 8 
     | 
    
         
            +
                #            (: <http://example/>))
         
     | 
| 
      
 9 
     | 
    
         
            +
                #     (reduced
         
     | 
| 
      
 10 
     | 
    
         
            +
                #       (project (?v)
         
     | 
| 
      
 11 
     | 
    
         
            +
                #         (bgp (triple ?x ?p ?v)))))
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 14 
     | 
    
         
            +
                class Reduced < Operator::Unary
         
     | 
| 
      
 15 
     | 
    
         
            +
                  include Query
         
     | 
| 
      
 16 
     | 
    
         
            +
                  
         
     | 
| 
      
 17 
     | 
    
         
            +
                  NAME = [:reduced]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # Executes this query on the given `queryable` graph or repository.
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # Removes duplicate solutions from the solution set.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @param  [RDF::Queryable] queryable
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #   the graph or repository to query
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @param  [Hash{Symbol => Object}] options
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   any additional keyword options
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @return [RDF::Query::Solutions]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #   the resulting solution sequence
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @see    http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def execute(queryable, options = {})
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @solutions = operands.last.
         
     | 
| 
      
 32 
     | 
    
         
            +
                      execute(queryable, options.merge(:depth => options[:depth].to_i + 1)).
         
     | 
| 
      
 33 
     | 
    
         
            +
                      reduced
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  
         
     | 
| 
      
 36 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # Returns an optimized version of this query.
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # Return optimized query
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # @return [Union, RDF::Query] `self`
         
     | 
| 
      
 42 
     | 
    
         
            +
                  def optimize
         
     | 
| 
      
 43 
     | 
    
         
            +
                    operands = operands.map(&:optimize)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end # Reduced
         
     | 
| 
      
 46 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 47 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL `regex` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   (prefix ((ex: <http://example.com/#>)
         
     | 
| 
      
 8 
     | 
    
         
            +
                #            (rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>))
         
     | 
| 
      
 9 
     | 
    
         
            +
                #     (project (?val)
         
     | 
| 
      
 10 
     | 
    
         
            +
                #       (filter (regex ?val "GHI")
         
     | 
| 
      
 11 
     | 
    
         
            +
                #         (bgp (triple ex:foo rdf:value ?val)))))
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @see http://www.w3.org/TR/rdf-sparql-query/#funcex-regex
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @see http://www.w3.org/TR/xpath-functions/#func-matches
         
     | 
| 
      
 15 
     | 
    
         
            +
                class Regex < Operator::Ternary
         
     | 
| 
      
 16 
     | 
    
         
            +
                  include Evaluatable
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  NAME = :regex
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # Initializes a new operator instance.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @param  [RDF::Term] text
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @param  [RDF::Term] pattern
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @param  [RDF::Term] flags
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # @param  [Hash{Symbol => Object}] options
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   any additional options (see {Operator#initialize})
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @raise  [TypeError] if any operand is invalid
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def initialize(text, pattern, flags = RDF::Literal(''), options = {})
         
     | 
| 
      
 30 
     | 
    
         
            +
                    super
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # Matches `text` against a regular expression `pattern`.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # @param  [RDF::Literal] text
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #   a simple literal
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # @param  [RDF::Literal] pattern
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #   a simple literal
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # @param  [RDF::Literal] flags
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #   a simple literal (defaults to an empty string)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  # @return [RDF::Literal::Boolean] `true` or `false`
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # @raise  [TypeError] if any operand is unbound
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # @raise  [TypeError] if any operand is not a simple literal
         
     | 
| 
      
 45 
     | 
    
         
            +
                  def apply(text, pattern, flags = RDF::Literal(''))
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # @see http://www.w3.org/TR/xpath-functions/#regex-syntax
         
     | 
| 
      
 47 
     | 
    
         
            +
                    raise TypeError, "expected a plain RDF::Literal, but got #{text.inspect}" unless text.is_a?(RDF::Literal) && text.plain?
         
     | 
| 
      
 48 
     | 
    
         
            +
                    text = text.to_s
         
     | 
| 
      
 49 
     | 
    
         
            +
                    # TODO: validate text syntax
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    # @see http://www.w3.org/TR/xpath-functions/#regex-syntax
         
     | 
| 
      
 52 
     | 
    
         
            +
                    raise TypeError, "expected a plain RDF::Literal, but got #{pattern.inspect}" unless pattern.is_a?(RDF::Literal) && pattern.plain?
         
     | 
| 
      
 53 
     | 
    
         
            +
                    pattern = pattern.to_s
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # TODO: validate pattern syntax
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    # @see http://www.w3.org/TR/xpath-functions/#flags
         
     | 
| 
      
 57 
     | 
    
         
            +
                    raise TypeError, "expected a plain RDF::Literal, but got #{flags.inspect}" unless flags.is_a?(RDF::Literal) && flags.plain?
         
     | 
| 
      
 58 
     | 
    
         
            +
                    flags = flags.to_s
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # TODO: validate flag syntax
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    options = 0
         
     | 
| 
      
 62 
     | 
    
         
            +
                    raise NotImplementedError, "unsupported regular expression flag: /s" if flags.include?(?s) # FIXME
         
     | 
| 
      
 63 
     | 
    
         
            +
                    options |= Regexp::MULTILINE  if flags.include?(?m)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    options |= Regexp::IGNORECASE if flags.include?(?i)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    options |= Regexp::EXTENDED   if flags.include?(?x)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    RDF::Literal(Regexp.new(pattern, options) === text)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                end # Regex
         
     | 
| 
      
 69 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 70 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL `sameTerm` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
         
     | 
| 
      
 8 
     | 
    
         
            +
                #            (: <http://example.org/things#>))
         
     | 
| 
      
 9 
     | 
    
         
            +
                #     (project (?x ?v)
         
     | 
| 
      
 10 
     | 
    
         
            +
                #       (filter (sameTerm ?v)
         
     | 
| 
      
 11 
     | 
    
         
            +
                #         (bgp (triple ?x :p ?v)))))
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @see http://www.w3.org/TR/rdf-sparql-query/#func-sameTerm
         
     | 
| 
      
 14 
     | 
    
         
            +
                class SameTerm < Operator::Binary
         
     | 
| 
      
 15 
     | 
    
         
            +
                  include Evaluatable
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  NAME = :sameTerm
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # Returns `true` if the operands are the same RDF term; returns
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # `false` otherwise.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @param  [RDF::Term] term1
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #   an RDF term
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @param  [RDF::Term] term2
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   an RDF term
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @return [RDF::Literal::Boolean] `true` or `false`
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @raise  [TypeError] if either operand is unbound
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def apply(term1, term2)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    RDF::Literal(term1.eql?(term2))
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # Returns an optimized version of this expression.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # @return [SPARQL::Algebra::Expression]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  def optimize
         
     | 
| 
      
 38 
     | 
    
         
            +
                    if operand(0).is_a?(Variable) && operand(0).eql?(operand(1))
         
     | 
| 
      
 39 
     | 
    
         
            +
                      RDF::Literal::TRUE
         
     | 
| 
      
 40 
     | 
    
         
            +
                    else
         
     | 
| 
      
 41 
     | 
    
         
            +
                      super # @see Operator#optimize
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end # SameTerm
         
     | 
| 
      
 45 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 46 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL GraphPattern `slice` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   (prefix ((: <http://example.org/ns#>))
         
     | 
| 
      
 8 
     | 
    
         
            +
                #     (slice 1 1
         
     | 
| 
      
 9 
     | 
    
         
            +
                #       (project (?v)
         
     | 
| 
      
 10 
     | 
    
         
            +
                #         (order (?v)
         
     | 
| 
      
 11 
     | 
    
         
            +
                #           (bgp (triple ??0 :num ?v))))))
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 14 
     | 
    
         
            +
                class Slice < Operator::Ternary
         
     | 
| 
      
 15 
     | 
    
         
            +
                  include Query
         
     | 
| 
      
 16 
     | 
    
         
            +
                  
         
     | 
| 
      
 17 
     | 
    
         
            +
                  NAME = [:slice]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # Executes this query on the given `queryable` graph or repository.
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # Returns a subset of the solutions resulting from executing
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # the third operand, an RDF::Queryable object by indexing in to the
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # result set by the amount specified in the first operand and limiting
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # the total number of solutions returned by the amount specified in the
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # second operand.
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # If either the first or second operands are `:_`, they are not considered.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #   (slice 1 2 (bgp (triple ?s ?p ?o)))   # Returns at most two solutions starting with the second solution.
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #   (slice _ 2 (bgp (triple ?s ?p ?o)))   # Returns at most two solutions starting with the first solution.
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   (slice 1 _ (bgp (triple ?s ?p ?o)))   # Returns all solution after the first.
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @param  [RDF::Queryable] queryable
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   the graph or repository to query
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @param  [Hash{Symbol => Object}] options
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #   any additional keyword options
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # @return [RDF::Query::Solutions]
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #   the resulting solution sequence
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # @see    http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 42 
     | 
    
         
            +
                  def execute(queryable, options = {})
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @solutions = operands.last. execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @solutions.offset(operands[0]) unless operands[0] == :_
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @solutions.limit(operands[1]) unless operands[1] == :_
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @solutions
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  
         
     | 
| 
      
 49 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 50 
     | 
    
         
            +
                  # Returns an optimized version of this query.
         
     | 
| 
      
 51 
     | 
    
         
            +
                  #
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # Return optimized query
         
     | 
| 
      
 53 
     | 
    
         
            +
                  #
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # @return [Union, RDF::Query] `self`
         
     | 
| 
      
 55 
     | 
    
         
            +
                  def optimize
         
     | 
| 
      
 56 
     | 
    
         
            +
                    operands = operands.map(&:optimize)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end # Slice
         
     | 
| 
      
 59 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 60 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL `str` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   (prefix ((xsd: <http://www.w3.org/2001/XMLSchema#>)
         
     | 
| 
      
 8 
     | 
    
         
            +
                #            (: <http://example.org/things#>))
         
     | 
| 
      
 9 
     | 
    
         
            +
                #     (project (?x ?v)
         
     | 
| 
      
 10 
     | 
    
         
            +
                #       (filter (= (str ?v) "1")
         
     | 
| 
      
 11 
     | 
    
         
            +
                #         (bgp (triple ?x :p ?v)))))
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @see http://www.w3.org/TR/rdf-sparql-query/#func-str
         
     | 
| 
      
 14 
     | 
    
         
            +
                class Str < Operator::Unary
         
     | 
| 
      
 15 
     | 
    
         
            +
                  include Evaluatable
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  NAME = :str
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # Returns the string form of the operand.
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # @param  [RDF::Literal, RDF::URI] term
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #   a literal or IRI
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @return [RDF::Literal] a simple literal
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @raise  [TypeError] if the operand is not a literal or IRI
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def apply(term)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    case term
         
     | 
| 
      
 28 
     | 
    
         
            +
                      when RDF::Literal then RDF::Literal(term.value)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      when RDF::URI     then RDF::Literal(term.to_s)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      else raise TypeError, "expected an RDF::Literal or RDF::URI, but got #{term.inspect}"
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end # Str
         
     | 
| 
      
 34 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 35 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL numeric `subtract` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #   (- ?x ?y)
         
     | 
| 
      
 6 
     | 
    
         
            +
                #   (subtract ?x ?y)
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @see http://www.w3.org/TR/xpath-functions/#func-numeric-subtract
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Subtract < Operator::Binary
         
     | 
| 
      
 10 
     | 
    
         
            +
                  include Evaluatable
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  NAME = [:-, :subtract]
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # Returns the arithmetic difference of the operands.
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # @param  [RDF::Literal::Numeric] left
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #   a numeric literal
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # @param  [RDF::Literal::Numeric] right
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #   a numeric literal
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # @return [RDF::Literal::Numeric]
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # @raise  [TypeError] if either operand is not a numeric literal
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def apply(left, right)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    case
         
     | 
| 
      
 25 
     | 
    
         
            +
                      when left.is_a?(RDF::Literal::Numeric) && right.is_a?(RDF::Literal::Numeric)
         
     | 
| 
      
 26 
     | 
    
         
            +
                        left - right
         
     | 
| 
      
 27 
     | 
    
         
            +
                      else raise TypeError, "expected two RDF::Literal::Numeric operands, but got #{left.inspect} and #{right.inspect}"
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end # Subtract
         
     | 
| 
      
 31 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 32 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Operator
         
     | 
| 
      
 3 
     | 
    
         
            +
                ##
         
     | 
| 
      
 4 
     | 
    
         
            +
                # The SPARQL GraphPattern `union` operator.
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   (prefix ((: <http://example/>))
         
     | 
| 
      
 8 
     | 
    
         
            +
                #     (union
         
     | 
| 
      
 9 
     | 
    
         
            +
                #       (bgp (triple ?s ?p ?o))
         
     | 
| 
      
 10 
     | 
    
         
            +
                #       (graph ?g
         
     | 
| 
      
 11 
     | 
    
         
            +
                #         (bgp (triple ?s ?p ?o)))))
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @see http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 14 
     | 
    
         
            +
                class Union < Operator::Binary
         
     | 
| 
      
 15 
     | 
    
         
            +
                  include Query
         
     | 
| 
      
 16 
     | 
    
         
            +
                  
         
     | 
| 
      
 17 
     | 
    
         
            +
                  NAME = [:union]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # Executes each operand with `queryable` and performs the `union` operation
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # by creating a new solution set consiting of all solutions from both operands.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @param  [RDF::Queryable] queryable
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #   the graph or repository to query
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @param  [Hash{Symbol => Object}] options
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   any additional keyword options
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @return [RDF::Query::Solutions]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #   the resulting solution sequence
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @see    http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def execute(queryable, options = {})
         
     | 
| 
      
 31 
     | 
    
         
            +
                    debug(options) {"Union"}
         
     | 
| 
      
 32 
     | 
    
         
            +
                    solutions1 = operand(0).execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
         
     | 
| 
      
 33 
     | 
    
         
            +
                    debug(options) {"=>(left) #{solutions1.inspect}"}
         
     | 
| 
      
 34 
     | 
    
         
            +
                    solutions2 = operand(1).execute(queryable, options.merge(:depth => options[:depth].to_i + 1))
         
     | 
| 
      
 35 
     | 
    
         
            +
                    debug(options) {"=>(right) #{solutions2.inspect}"}
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @solutions = RDF::Query::Solutions.new(solutions1 + solutions2)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    debug(options) {"=> #{@solutions.inspect}"}
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @solutions
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  
         
     | 
| 
      
 41 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 42 
     | 
    
         
            +
                  # Returns an optimized version of this query.
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # If optimize operands, and if the first two operands are both Queries, replace
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # with the unique sum of the query elements
         
     | 
| 
      
 46 
     | 
    
         
            +
                  #
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # @return [Union, RDF::Query] `self`
         
     | 
| 
      
 48 
     | 
    
         
            +
                  def optimize
         
     | 
| 
      
 49 
     | 
    
         
            +
                    ops = operands.map {|o| o.optimize }.select {|o| o.respond_to?(:empty?) && !o.empty?}
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @operands = ops
         
     | 
| 
      
 51 
     | 
    
         
            +
                    self
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
                end # Union
         
     | 
| 
      
 54 
     | 
    
         
            +
              end # Operator
         
     | 
| 
      
 55 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     | 
| 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SPARQL; module Algebra
         
     | 
| 
      
 2 
     | 
    
         
            +
              ##
         
     | 
| 
      
 3 
     | 
    
         
            +
              # A SPARQL algebra query, may be duck-typed as RDF::Query.
         
     | 
| 
      
 4 
     | 
    
         
            +
              #
         
     | 
| 
      
 5 
     | 
    
         
            +
              # Mixin with SPARQL::Algebra::Operator to provide query-like operations on graphs and filters
         
     | 
| 
      
 6 
     | 
    
         
            +
              #
         
     | 
| 
      
 7 
     | 
    
         
            +
              # @abstract
         
     | 
| 
      
 8 
     | 
    
         
            +
              module Query
         
     | 
| 
      
 9 
     | 
    
         
            +
                ##
         
     | 
| 
      
 10 
     | 
    
         
            +
                # Prepends an operator.
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                # @param  [RDF::Query] query
         
     | 
| 
      
 13 
     | 
    
         
            +
                #   a query
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @return [void] self
         
     | 
| 
      
 15 
     | 
    
         
            +
                def unshift(query)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @operands.unshift(query)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  self
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
                
         
     | 
| 
      
 20 
     | 
    
         
            +
                ##
         
     | 
| 
      
 21 
     | 
    
         
            +
                # The variables used in this query.
         
     | 
| 
      
 22 
     | 
    
         
            +
                #
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @return [Hash{Symbol => RDF::Query::Variable}]
         
     | 
| 
      
 24 
     | 
    
         
            +
                def variables
         
     | 
| 
      
 25 
     | 
    
         
            +
                  operands.inject({}) {|hash, o| o.executable? ? hash.merge!(o.variables) : hash}
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                ##
         
     | 
| 
      
 29 
     | 
    
         
            +
                # The solution sequence for this query.
         
     | 
| 
      
 30 
     | 
    
         
            +
                #
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @return [RDF::Query::Solutions]
         
     | 
| 
      
 32 
     | 
    
         
            +
                attr_reader :solutions
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                ##
         
     | 
| 
      
 35 
     | 
    
         
            +
                # Executes this query on the given `queryable` graph or repository.
         
     | 
| 
      
 36 
     | 
    
         
            +
                #
         
     | 
| 
      
 37 
     | 
    
         
            +
                # @param  [RDF::Queryable] queryable
         
     | 
| 
      
 38 
     | 
    
         
            +
                #   the graph or repository to query
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @param  [Hash{Symbol => Object}] options
         
     | 
| 
      
 40 
     | 
    
         
            +
                #   any additional keyword options
         
     | 
| 
      
 41 
     | 
    
         
            +
                # @option options [Boolean] debug
         
     | 
| 
      
 42 
     | 
    
         
            +
                #   Query execution debugging
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @return [RDF::Query::Solutions]
         
     | 
| 
      
 44 
     | 
    
         
            +
                #   the resulting solution sequence
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @raise [TypeError]
         
     | 
| 
      
 46 
     | 
    
         
            +
                #   TypeError raised if any operands are invalid
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @raise [NotImplementedError]
         
     | 
| 
      
 48 
     | 
    
         
            +
                #   If an attempt is made to perform an unsupported operation
         
     | 
| 
      
 49 
     | 
    
         
            +
                # @see    http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra
         
     | 
| 
      
 50 
     | 
    
         
            +
                def execute(queryable, options = {})
         
     | 
| 
      
 51 
     | 
    
         
            +
                  raise NotImplementedError, "#{self.class}#execute(#{queryable})"
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                # Add context to sub-items, unless they already have a context
         
     | 
| 
      
 55 
     | 
    
         
            +
                # @param [RDF::URI, RDF::Query::Variable] value
         
     | 
| 
      
 56 
     | 
    
         
            +
                # @return [RDF::URI, RDF::Query::Variable]
         
     | 
| 
      
 57 
     | 
    
         
            +
                def context=(value)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  operands.each do |operand|
         
     | 
| 
      
 59 
     | 
    
         
            +
                    operand.context = value if operand.respond_to?(:context) && operand.context != false
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  value
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                ##
         
     | 
| 
      
 65 
     | 
    
         
            +
                # Returns `true` if this query did not match when last executed.
         
     | 
| 
      
 66 
     | 
    
         
            +
                #
         
     | 
| 
      
 67 
     | 
    
         
            +
                # When the solution sequence is empty, this method can be used to
         
     | 
| 
      
 68 
     | 
    
         
            +
                # determine whether the query failed to match or not.
         
     | 
| 
      
 69 
     | 
    
         
            +
                #
         
     | 
| 
      
 70 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 71 
     | 
    
         
            +
                # @see    #matched?
         
     | 
| 
      
 72 
     | 
    
         
            +
                def failed?
         
     | 
| 
      
 73 
     | 
    
         
            +
                  solutions.empty?
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                ##
         
     | 
| 
      
 77 
     | 
    
         
            +
                # Returns `true` if this query matched when last executed.
         
     | 
| 
      
 78 
     | 
    
         
            +
                #
         
     | 
| 
      
 79 
     | 
    
         
            +
                # When the solution sequence is empty, this method can be used to
         
     | 
| 
      
 80 
     | 
    
         
            +
                # determine whether the query matched successfully or not.
         
     | 
| 
      
 81 
     | 
    
         
            +
                #
         
     | 
| 
      
 82 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 83 
     | 
    
         
            +
                # @see    #failed?
         
     | 
| 
      
 84 
     | 
    
         
            +
                def matched?
         
     | 
| 
      
 85 
     | 
    
         
            +
                  !failed?
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                ##
         
     | 
| 
      
 89 
     | 
    
         
            +
                # Enumerates over each matching query solution.
         
     | 
| 
      
 90 
     | 
    
         
            +
                #
         
     | 
| 
      
 91 
     | 
    
         
            +
                # @yield  [solution]
         
     | 
| 
      
 92 
     | 
    
         
            +
                # @yieldparam [RDF::Query::Solution] solution
         
     | 
| 
      
 93 
     | 
    
         
            +
                # @return [Enumerator]
         
     | 
| 
      
 94 
     | 
    
         
            +
                def each_solution(&block)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  solutions.each(&block)
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
                alias_method :each, :each_solution
         
     | 
| 
      
 98 
     | 
    
         
            +
              end # Query
         
     | 
| 
      
 99 
     | 
    
         
            +
            end; end # SPARQL::Algebra
         
     |