Class: RDF::Query

Inherits:
Object show all
Includes:
Enumerable
Defined in:
vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb,
vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query/hash_pattern_normalizer.rb,
vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query/pattern.rb,
vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query/solution.rb,
vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query/solutions.rb,
vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query/variable.rb,
vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb

Overview

An RDF basic graph pattern (BGP) query.

Named queries either match against a specifically named contexts if the name is an RDF::Resource or bound RDF::Query::Variable. Names that are against unbound variables match either default or named contexts. The name of false will only match against the default context.

Variable names cause the variable to be added to the solution set elements.

Examples:

Constructing a basic graph pattern query (1)

query = RDF::Query.new do
  pattern [:person, RDF.type,  FOAF.Person]
  pattern [:person, FOAF.name, :name]
  pattern [:person, FOAF.mbox, :email]
end

Constructing a basic graph pattern query (2)

query = RDF::Query.new({
  :person => {
    RDF.type  => FOAF.Person,
    FOAF.name => :name,
    FOAF.mbox => :email,
  }
})

Executing a basic graph pattern query

graph = RDF::Graph.load('etc/doap.nt')
query.execute(graph).each do |solution|
  puts solution.inspect
end

Constructing and executing a query in one go (1)

solutions = RDF::Query.execute(graph) do
  pattern [:person, RDF.type, FOAF.Person]
end

Constructing and executing a query in one go (2)

solutions = RDF::Query.execute(graph, {
  :person => {
    RDF.type => FOAF.Person,
  }
})

In this example, the default graph contains the names of the publishers of two named graphs. The triples in the named graphs are not visible in the default graph in this example.

# default graph
@prefix dc: <http://purl.org/dc/elements/1.1/

<http://example.org/bob>    dc:publisher  "Bob" .
<http://example.org/alice>  dc:publisher  "Alice" .

# Named graph: http://example.org/bob
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

_:a foaf:name "Bob" .
_:a foaf:mbox <mailto:bob@oldcorp.example.org> .

# Named graph: http://example.org/alice
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example.org> .

See Also:

Since:

Direct Known Subclasses

SPARQL::Client::Query

Defined Under Namespace

Classes: HashPatternNormalizer, Pattern, Solution, Solutions, Variable

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Enumerable

add_entailment, #contexts, #dump, #each_context, #each_graph, #each_object, #each_predicate, #each_quad, #each_subject, #each_triple, #entail, #enum_context, #enum_graph, #enum_object, #enum_predicate, #enum_quad, #enum_statement, #enum_subject, #enum_triple, #has_context?, #has_object?, #has_predicate?, #has_quad?, #has_statement?, #has_subject?, #has_triple?, #invalid?, #method_missing, #objects, #predicates, #quads, #statements, #subjects, #supports?, #to_a, #to_hash, #to_set, #triples

Methods included from Util::Aliasing::LateBound

#alias_method

Methods included from Isomorphic

#bijection_to, #isomorphic_with?

Methods included from Countable

#count

Constructor Details

- (Query) initialize(patterns = [], options = {}) {|query| ... } - (Query) initialize(patterns, options = {}) {|query| ... }

Initializes a new basic graph pattern query.

Overloads:

  • - (Query) initialize(patterns = [], options = {}) {|query| ... }

    Parameters:

    Options Hash (options):

    • :solutions (RDF::Query::Solutions) — default: Solutions.new
    • :context (RDF::Resource, RDF::Query::Variable, false) — default: nil

      Default context for matching against queryable. Named queries either match against a specifically named graphs if the name is an Resource or bound Variable. Names that are against unbound variables match either default or named graphs. The name of false will only match against the default context.

    • :name (RDF::Resource, RDF::Query::Variable, false) — default: nil

      Alias for :context.

    Yields:

    • (query)

    Yield Parameters:

    Yield Returns:

    • (void)

      ignored

  • - (Query) initialize(patterns, options = {}) {|query| ... }

    Parameters:

    Options Hash (options):

    Yields:

    • (query)

    Yield Parameters:

    Yield Returns:

    • (void)

      ignored

Since:

  • 0.3.0



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 180

def initialize(*patterns, &block)
  @options  = patterns.last.is_a?(Hash) ? patterns.pop.dup : {}
  patterns << @options if patterns.empty?
  @variables = {}
  @solutions = Query::Solutions(@options.delete(:solutions))
  context = @options.fetch(:context, @options.fetch(:name, nil))
  @options.delete(:context)
  @options.delete(:name)

  @patterns  = case patterns.first
    when Hash  then compile_hash_patterns(HashPatternNormalizer.normalize!(patterns.first.dup, @options))
    when Array then patterns.first
    else patterns
  end

  self.context = context

  if block_given?
    case block.arity
      when 1 then block.call(self)
      else instance_eval(&block)
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RDF::Enumerable

Instance Attribute Details

- (Hash) options (readonly)

Any additional options for this query.

Returns:

Since:

  • 0.3.0



139
140
141
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 139

def options
  @options
end

- (Array<RDF::Query::Pattern>) patterns (readonly)

The patterns that constitute this query.

Returns:

Since:

  • 0.3.0



127
128
129
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 127

def patterns
  @patterns
end

- (RDF::Query::Solutions) solutions (readonly)

The solution sequence for this query.

Returns:

Since:

  • 0.3.0



133
134
135
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 133

def solutions
  @solutions
end

- (Hash{Symbol => RDF::Query::Variable}) variables (readonly)

The variables used in this query.

Returns:

Since:

  • 0.3.0



121
122
123
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 121

def variables
  @variables
end

Class Method Details

+ (RDF::Query::Solutions) execute(queryable, patterns = {}, options = {}) {|query| ... }

Executes a query on the given queryable graph or repository.

Parameters:

Yields:

  • (query)

Yield Parameters:

Yield Returns:

  • (void)

    ignored

Returns:

See Also:

Since:

  • 0.3.0



92
93
94
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 92

def self.execute(queryable, patterns = {}, options = {}, &block)
  self.new(patterns, options, &block).execute(queryable, options)
end

+ (Solutions) Solutions + (Solutions) Solutions(solutions) + (Solutions) Solutions(array) + (Solutions) Solutions(*args)

Cast values as Solutions

Overloads:

  • + (Solutions) Solutions

    Returns Solutions.new()

    Returns:

  • + (Solutions) Solutions(solutions)

    Returns the argument

    Returns:

  • + (Solutions) Solutions(array)

    Returns the array extended with solutions

    Parameters:

    Returns:

    • (Solutions)

      returns the array extended with solutions

  • + (Solutions) Solutions(*args)

    Returns new solutions including the arguments, which must each be a Solution

    Parameters:

    Returns:

    • (Solutions)

      returns new solutions including the arguments, which must each be a Solution

Since:

  • 0.3.0



111
112
113
114
115
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 111

def self.Solutions(*args)
  return args.first if args.length == 1 && args.first.is_a?(Solutions)
  args = args.first if args.first.is_a?(Array) && args.length == 1
  return Solutions.new(args)
end

Instance Method Details

- (RDF::Query) +(other)

Add patterns from another query to form a new Query

Parameters:

Returns:

Since:

  • 0.3.0



398
399
400
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 398

def +(other)
  Query.new(self.patterns + other.patterns)
end

- <<(pattern)

This method returns an undefined value.

Appends the given query pattern to this query.

Parameters:

Since:

  • 0.3.0



211
212
213
214
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 211

def <<(pattern)
  @patterns << Pattern.from(pattern)
  self
end

- (Boolean) ==(other)

Equivalence for Queries: Same Patterns Same Context

Returns:

  • (Boolean)

Since:

  • 0.3.0



315
316
317
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 315

def ==(other)
  other.is_a?(RDF::Query) && patterns == other.patterns && context == context
end

- (Object) apply_context(context = options[:context])

Apply the context specified (or configured) to all patterns that have no context

Parameters:

Since:

  • 0.3.0



436
437
438
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 436

def apply_context(context = options[:context])
  patterns.each {|pattern| pattern.context = context if pattern.context.nil?} unless context.nil?
end

- (RDF::IRI, RDF::Query::Variable) context

Scope of this query, if any

Returns:

Since:

  • 0.3.0



430
431
432
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 430

def context
  options[:context]
end

- (RDF::IRI, RDF::Query::Variable) context=(value)

Scope the query to named graphs matching value

Parameters:

Returns:

Since:

  • 0.3.0



424
425
426
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 424

def context=(value)
  options[:context] = value
end

- (Boolean) default?

Is this query scoped to the default graph?

Returns:

  • (Boolean)

Since:

  • 0.3.0



410
411
412
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 410

def default?
  options[:context] == false
end

- (RDF::Query) dup

Duplicate query, including patterns and solutions

Returns:

Since:

  • 0.3.0



487
488
489
490
491
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 487

def dup
  patterns = @patterns.map {|p| p.dup}
  patterns << @options.merge(:solutions => @solutions.dup)
  Query.new(*patterns)
end

- (Enumerator) each_solution {|solution| ... } Also known as: each

Enumerates over each matching query solution.

Yields:

  • (solution)

Yield Parameters:

Returns:

Since:

  • 0.3.0



468
469
470
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 468

def each_solution(&block)
  @solutions.each(&block)
end

- (Enumerator) each_statement {|RDF::Query::Pattern| ... }

Enumerates over each statement (pattern).

Yields:

Yield Parameters:

  • pattern (::Query::Pattern)

Returns:

Since:

  • 0.3.0



479
480
481
482
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 479

def each_statement(&block)
  apply_context
  patterns.each(&block)
end

- (Boolean) empty?

Query has no patterns

Returns:

  • (Boolean)

Since:

  • 0.3.0



458
459
460
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 458

def empty?
  patterns.empty?
end

- (RDF::Query::Solutions) execute(queryable, options = {}) {|solution| ... }

Executes this query on the given queryable graph or repository.

Named queries either match against a specifically named contexts if the name is an RDF::Resource or bound RDF::Query::Variable. Names that are against unbound variables match either detault or named contexts. The name of false will only match against the default context.

If the query nas no patterns, it returns a single empty solution as per SPARQL 1.1 Empty Group Pattern.

Parameters:

  • queryable (RDF::Queryable)

    the graph or repository to query

  • options (Hash{Symbol => Object}) (defaults to: {})

    any additional keyword options

Options Hash (options):

Yields:

  • (solution)

    each matching solution

Yield Parameters:

Yield Returns:

  • (void)

    ignored

Returns:

See Also:

Since:

  • 0.3.0



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 291

def execute(queryable, options = {}, &block)
  validate!
  options = options.dup

  # just so we can call #keys below without worrying
  options[:bindings] ||= {}

  # Use provided solutions to allow for query chaining
  # Otherwise, a quick empty solution simplifies the logic below; no special case for
  # the first pattern
  @solutions = Query::Solutions(options[:solutions] || Solution.new)

  # If there are no patterns, just return the empty solution
  if empty?
    @solutions.each(&block) if block_given?
    return @solutions
  end

  patterns = @patterns
  context = options.fetch(:context, options.fetch(:name, self.context))

  # Add context to pattern, if necessary
  unless context.nil?
    if patterns.empty?
      patterns = [Pattern.new(nil, nil, nil, :context => context)]
    else
      apply_context(context)
    end
  end

  patterns.each do |pattern|

    old_solutions, @solutions = @solutions, Query::Solutions()

    options[:bindings].keys.each do |variable|
      if pattern.variables.include?(variable)
        unbound_solutions, old_solutions = old_solutions, Query::Solutions()
        options[:bindings][variable].each do |binding|
          unbound_solutions.each do |solution|
            old_solutions << solution.merge(variable => binding)
          end
        end
        options[:bindings].delete(variable)
      end
    end

    old_solutions.each do |solution|
      found_match = false
      pattern.execute(queryable, solution) do |statement|
        found_match = true
        @solutions << solution.merge(pattern.solution(statement))
      end
      # If this pattern was optional, and we didn't find any matches,
      # just copy it over as-is.
      if !found_match && pattern.optional?
        @solutions << solution
      end
    end

    #puts "solutions after #{pattern} are #{@solutions.to_a.inspect}"

    # It's important to abort failed queries quickly because later patterns
    # that can have constraints are often broad without them.
    # We have no solutions at all:
    return @solutions if @solutions.empty?

    if !pattern.optional?
      # We have no solutions for variables we should have solutions for:
      need_vars = pattern.variables.keys
      @solutions.each do |solution|
        break if need_vars.empty?
        need_vars -= solution.bindings.keys
      end
      return Query::Solutions() unless need_vars.empty?
    end
  end
  @solutions.each(&block) if block_given?
  @solutions
end

- (Boolean) failed?

Returns true if this query did not match when last executed.

When the solution sequence is empty, this method can be used to determine whether the query failed to match or not.

Returns:

  • (Boolean)

See Also:

Since:

  • 0.3.0



379
380
381
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 379

def failed?
  @solutions.empty?
end

- (Boolean) has_blank_nodes?

Returns true if any pattern contains a blank node.

Returns:

  • (Boolean)

Since:

  • 0.3.0



452
453
454
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 452

def has_blank_nodes?
  patterns.any?(&:has_blank_nodes?) || context && context.node?
end

- (Boolean) matched?

Returns true if this query matched when last executed.

When the solution sequence is empty, this method can be used to determine whether the query matched successfully or not.

Returns:

  • (Boolean)

See Also:

Since:

  • 0.3.0



391
392
393
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 391

def matched?
  !failed?
end

- (Boolean) named?

Is this query scoped to a named graph?

Returns:

  • (Boolean)

Since:

  • 0.3.0



404
405
406
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 404

def named?
  !!options[:context]
end

- (Array<RDF::Query::Variable>) ndvars

Return the non-destinguished variables contained within patterns

Returns:

Since:

  • 0.3.0



363
364
365
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 363

def ndvars
  patterns.map(&:ndvars).flatten
end

- (RDF::Query) optimize(options = {})

Returns an optimized copy of this query.

Parameters:

  • options (Hash{Symbol => Object}) (defaults to: {})

    any additional options for optimization

Returns:

Since:

  • 0.3.0



238
239
240
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 238

def optimize(options = {})
  self.dup.optimize!(options)
end

- optimize!(options = {})

This method returns an undefined value.

Optimizes this query by reordering its constituent triple patterns according to their cost estimates.

Parameters:

  • options (Hash{Symbol => Object}) (defaults to: {})

    any additional options for optimization

See Also:

Since:

  • 0.3.0



251
252
253
254
255
256
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 251

def optimize!(options = {})
  @patterns.sort! do |a, b|
    (a.cost || 0) <=> (b.cost || 0)
  end
  self
end

- pattern(pattern, options = {})

This method returns an undefined value.

Appends the given query pattern to this query.

Parameters:

Options Hash (options):

  • :optional (Boolean) — default: false

    whether this is an optional pattern

Since:

  • 0.3.0



226
227
228
229
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 226

def pattern(pattern, options = {})
  @patterns << Pattern.from(pattern, options)
  self
end

- (Boolean) query_yields_boolean?

Query results in a boolean result (e.g., ASK)

Returns:

  • (Boolean)

Since:

  • 0.3.0



344
345
346
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 344

def query_yields_boolean?
  false
end

- (Boolean) query_yields_solutions?

Query results solutions (e.g., SELECT)

Returns:

  • (Boolean)

Since:

  • 0.3.0



356
357
358
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 356

def query_yields_solutions?
  true
end

- (Boolean) query_yields_statements?

Query results statements (e.g., CONSTRUCT, DESCRIBE, CREATE)

Returns:

  • (Boolean)

Since:

  • 0.3.0



350
351
352
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 350

def query_yields_statements?
  false
end

- (SPARQL::Algebra::Expression) rewrite(&block)

Don't do any more rewriting

Returns:

Since:

  • 0.3.0



322
323
324
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 322

def rewrite(&block)
  self
end

- (Array) to_sxp_bin

Transform Query into an Array form of an SSE

If Query has the as_container option set, serialize as Quads Otherwise, If Query is named, serialize as a GroupGraphPattern. Otherise, serialize as a BGP

Returns:

Since:

  • 0.3.0



333
334
335
336
337
338
339
340
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 333

def to_sxp_bin
  if options[:as_container]
    [:graph, context] + [patterns.map(&:to_sxp_bin)]
  else
    res = [:bgp] + patterns.map(&:to_sxp_bin)
    (context ? [:graph, context, res] : res)
  end
end

- (Boolean) unnamed?

Is this query unscoped? This indicates that it can return results from either a named graph or the default graph.

Returns:

  • (Boolean)

Since:

  • 0.3.0



417
418
419
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 417

def unnamed?
  options[:context].nil?
end

- (Boolean) valid?

Determine if the URI is a valid according to RFC3987

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.9



498
499
500
501
502
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 498

def valid?
  !!validate!
rescue
  false
end

- (RDF::Query) validate!

Validate this query, making sure it can be executed by our query engine. This method is public so that it may be called by implementations of RDF::Queryable#query_execute that bypass our built-in query engine.

Returns:

Raises:

  • (ArgumentError)

    This query cannot be executed.

Since:

  • 0.3.0



511
512
513
514
515
516
517
518
519
520
521
522
523
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 511

def validate!
  # All patterns must be valid
  @patterns.each(&:validate!)

  # All optional patterns must appear after the regular patterns.
  if i = @patterns.find_index(&:optional?)
    unless @patterns[i..-1].all?(&:optional?)
      raise ArgumentError.new("Optional patterns must appear at end of query")
    end
  end

  self
end

- (Boolean) variable?

Returns true if any pattern contains a variable.

Returns:

  • (Boolean)

Since:

  • 0.3.0



444
445
446
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/rdf-24bf82278685/lib/rdf/query.rb', line 444

def variable?
  patterns.any?(&:variable?) || context && context.variable?
end

- (Array<RDF::Query::Variable>) vars

Return the variables contained within patterns

Returns:

Since:

  • 0.3.0



370
371
372
# File 'vendor/bundler/ruby/2.1.0/bundler/gems/sparql-fb1fb1facc64/lib/sparql/algebra/extensions.rb', line 370

def vars
  patterns.map(&:vars).flatten
end