Class: RDF::Query::Pattern

Inherits:
Statement show all
Defined in:
vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb,
vendor/bundler/ruby/2.7.0/bundler/gems/sparql-cd4915d97d78/lib/sparql/algebra/extensions.rb

Overview

An RDF query pattern.

Since:

  • 0.3.0

Instance Attribute Summary collapse

Attributes inherited from Statement

#graph_name, #id, #object, #predicate, #subject

Instance Method Summary collapse

Methods inherited from Statement

#==, #===, #[], #[]=, add_entailment, #asserted?, #canonicalize, #canonicalize!, #complete?, #embedded?, #entail, #has_graph?, #has_object?, #has_predicate?, #has_subject?, #hash, #incomplete?, #inferred?, #invalid?, #node?, #optimize, #quoted?, #reified, #statement?, #to_h, #to_quad, #to_sxp, #to_triple, #valid_extended?, #variable?

Methods included from Resource

new, #resource?

Methods included from Term

#<=>, #==, #aggregate?, #compatible?, #escape, #evaluate, #optimize, #term?, #to_base, #to_term

Methods included from Value

#anonymous?, #canonicalize, #canonicalize!, #constant?, #graph?, #inspect, #inspect!, #invalid?, #iri?, #list?, #literal?, #node?, #resource?, #start_with?, #statement?, #term?, #to_nquads, #to_ntriples, #to_rdf, #to_term, #type_error, #uri?, #validate!, #variable?

Methods included from SPARQL::Algebra::Expression

cast, #constant?, #evaluate, extension, extensions, for, #invalid?, new, #node?, open, #optimize, #optimize!, parse, register_extension, #validate!, #variable?

Constructor Details

#initialize(options = {}) ⇒ Pattern #initialize(subject, predicate, object, options = {}) ⇒ Pattern

Note:

Statement treats symbols as interned Node instances, in a RDF::Query::Pattern, they are treated as Variable.

Returns a new instance of Pattern.

Overloads:

Since:

  • 0.3.0



39
40
41
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 39

def initialize(subject = nil, predicate = nil, object = nil, options = {})
  super
end

Instance Attribute Details

#costNumeric

The estimated cost of this pattern (for query optimization).

Returns:

  • (Numeric)

Since:

  • 0.3.0



72
73
74
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 72

def cost
  @cost
end

#optionsHash (readonly)

Any additional options for this pattern.

Returns:

Since:

  • 0.3.0



66
67
68
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 66

def options
  @options
end

Instance Method Details

#bind(solution) ⇒ self

Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables

Parameters:

Returns:

  • (self)

Since:

  • 0.3.0



280
281
282
283
284
285
286
287
288
289
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 280

def bind(solution)
  self.to_quad.each_with_index do |term, index|
    if term.is_a?(Variable) && solution[term]
      self[index] = solution[term] 
    elsif term.is_a?(Pattern)
      term.bind(solution)
    end
  end
  self
end

#binding_countInteger

Returns the number of bindings in this pattern.

Returns:

Since:

  • 0.3.0



303
304
305
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 303

def binding_count
  bindings.size
end

#bindingsHash{Symbol => RDF::Term}

Returns all bindings in this pattern.

Returns:

Since:

  • 0.3.0



311
312
313
314
315
316
317
318
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 311

def bindings
  bindings = {}
  bindings.merge!(subject.bindings)    if subject && subject.variable?
  bindings.merge!(predicate.bindings)  if predicate.is_a?(Variable)
  bindings.merge!(object.bindings)     if object && object.variable?
  bindings.merge!(graph_name.bindings) if graph_name.is_a?(Variable)
  bindings
end

#bindings?Boolean

Returns true if this pattern contains bindings.

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



295
296
297
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 295

def bindings?
  !bindings.empty?
end

#blank?Boolean

Returns true if this is a blank pattern, with all terms being nil.

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



79
80
81
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 79

def blank?
  subject.nil? && predicate.nil? && object.nil? && graph_name.nil?
end

#bound?Boolean

Returns true if all variables in this pattern are bound.

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



324
325
326
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 324

def bound?
  !variables.empty? && variables.values.all?(&:bound?)
end

#bound_variablesHash{Symbol => Variable}

Returns all bound variables in this pattern.

Returns:

Since:

  • 0.3.0



332
333
334
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 332

def bound_variables
  variables.reject { |name, variable| variable.unbound? }
end

#eql?(other) ⇒ Boolean

Checks pattern equality against a statement, considering nesting.

  • A pattern which has a pattern as a subject or an object, matches a statement having a statement as a subject or an object using #eql?.

Parameters:

Returns:

  • (Boolean)

See Also:

Since:

  • 0.3.0



135
136
137
138
139
140
141
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 135

def eql?(other)
  return false unless other.is_a?(Statement) && (self.graph_name || false) == (other.graph_name || false)

  predicate == other.predicate &&
  (subject.is_a?(Pattern) ? subject.eql?(other.subject) : subject == other.subject) &&
  (object.is_a?(Pattern) ? object.eql?(other.object) : object == other.object)
end

#execute(queryable, bindings = {}) {|statement| ... } ⇒ Enumerable<RDF::Query::Pattern>

Executes this query pattern on the given queryable object.

Values are matched using using Queryable#query_pattern.

If the optional bindings are given, variables will be substituted with their values when executing the query.

To match triples only in the default graph, set graph_name to false.

Examples:

Pattern.new(:s, :p, :o).execute(RDF::Repository.load('etc/doap.nt'))

Parameters:

Yields:

  • (statement)

    each matching statement

Yield Parameters:

  • statement (RDF::Statement)

    an RDF statement matching this pattern

Returns:

See Also:

Since:

  • 0.3.0



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 167

def execute(queryable, bindings = {}, &block)
  query = {
    subject:    subject.is_a?(Variable)     && bindings[subject.to_sym]     ? bindings[subject.to_sym]    : subject,
    predicate:  predicate.is_a?(Variable)   && bindings[predicate.to_sym]   ? bindings[predicate.to_sym]  : predicate,
    object:     object.is_a?(Variable)      && bindings[object.to_sym]      ? bindings[object.to_sym]     : object,
    graph_name: graph_name.is_a?(Variable)  && bindings[graph_name.to_sym]  ? bindings[graph_name.to_sym] : graph_name,
  }.delete_if{|k,v| v.nil?}

  # Do all the variable terms refer to distinct variables?
  variables = self.variables
  if variable_count == variables.size
    # If so, we can just let the repository implementation handle
    # everything and yield matching statements directly:
    queryable.query(query, &block)

  # No, some terms actually refer to the same variable...
  else
    # Figure out which terms refer to the same variable:
    terms = variables.each_key.find do |name|
      terms = variable_terms(name)
      break terms if terms.size > 1
    end
    queryable.query(query).select do |statement|
      # Only yield those matching statements where the variable
      # constraint is also satisfied:
      # FIXME: `Array#uniq` uses `#eql?` and `#hash`, not `#==`
      if terms.map { |term| statement.send(term) }.uniq.size.equal?(1)
        yield statement if block_given?
        true
      end
    end
  end
end

#has_variables?Boolean Also known as: variables?

Returns true if this pattern contains any variables.

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



88
89
90
91
92
93
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 88

def has_variables?
  subject    && subject.variable? ||
  predicate  && predicate.variable? ||
  object     && object.variable? ||
  graph_name && graph_name.variable?
end

#ndvarsArray<RDF::Query::Variable>

Return the non-destinguished variables contained within this pattern



460
461
462
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/sparql-cd4915d97d78/lib/sparql/algebra/extensions.rb', line 460

def ndvars
  vars.reject(&:distinguished?)
end

#optional?Boolean

Returns true if this is an optional pattern.

Examples:

Pattern.new(:s, :p, :o).optional?                     #=> false
Pattern.new(:s, :p, :o, optional: true).optional?  #=> true

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



105
106
107
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 105

def optional?
  !!options[:optional]
end

#solution(statement) ⇒ RDF::Query::Solution

Returns a query solution constructed by binding any variables in this pattern with the corresponding terms in the given statement.

Examples:

pattern = Pattern.new(:s, :p, :o)
solution = pattern.solution(statement)

pattern[:s] #=> statement.subject
pattern[:p] #=> statement.predicate
pattern[:o] #=> statement.object

Parameters:

Returns:

Since:

  • 0.3.0



217
218
219
220
221
222
223
224
225
226
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 217

def solution(statement)
  RDF::Query::Solution.new do |solution|
    solution[subject.to_sym]    = statement.subject    if subject.is_a?(Variable)
    solution[predicate.to_sym]  = statement.predicate  if predicate.is_a?(Variable)
    solution[object.to_sym]     = statement.object     if object.is_a?(Variable)
    solution[graph_name.to_sym] = statement.graph_name if graph_name.is_a?(Variable)
    solution.merge!(subject.solution(statement.subject)) if subject.is_a?(Pattern)
    solution.merge!(object.solution(statement.object)) if object.is_a?(Pattern)
  end
end

#to_sString

Returns a string representation of this pattern.

Returns:

Since:

  • 0.3.0



356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 356

def to_s
  StringIO.open do |buffer| # FIXME in RDF::Statement
    buffer << 'OPTIONAL ' if optional?
    buffer << [subject, predicate, object].map do |r|
      if r.is_a?(RDF::Query::Variable)
        r.to_s
      elsif r.is_a?(RDF::Query::Pattern)
        "<<#{r.to_s[0..-3]}>>"
      else
        RDF::NTriples.serialize(r)
      end
    end.join(" ")
    buffer << case graph_name
      when nil, false then " ."
      when Variable then " #{graph_name.to_s} ."
      else " #{RDF::NTriples.serialize(graph_name)} ."
    end
    buffer.string
  end
end

#to_sxp_binArray

Transform Query Pattern into an SXP

Returns:



449
450
451
452
453
454
455
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/sparql-cd4915d97d78/lib/sparql/algebra/extensions.rb', line 449

def to_sxp_bin
  if has_graph?
    [:quad, subject, predicate, object, graph_name]
  else
    [:triple, subject, predicate, object]
  end
end

#unbound?Boolean

Returns true if all variables in this pattern are unbound.

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



340
341
342
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 340

def unbound?
  !variables.empty? && variables.values.all?(&:unbound?)
end

#unbound_variablesHash{Symbol => Variable}

Returns all unbound variables in this pattern.

Returns:

Since:

  • 0.3.0



348
349
350
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 348

def unbound_variables
  variables.reject { |name, variable| variable.bound? }
end

#valid?Boolean

Is this pattern composed only of valid components?

Returns:

  • (Boolean)

    true or false

Since:

  • 0.3.0



113
114
115
116
117
118
119
120
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 113

def valid?
  (has_subject?   ? (subject.resource? || subject.variable?) && subject.valid? : true) && 
  (has_predicate? ? (predicate.uri? || predicate.variable?) && predicate.valid? : true) &&
  (has_object?    ? (object.term? || object.variable?) && object.valid? : true) &&
  (has_graph?     ? (graph_name.resource? || graph_name.variable?) && graph_name.valid? : true)
rescue NoMethodError
  false
end

#variable_countInteger Also known as: cardinality, arity

Returns the number of variables in this pattern.

Note: this does not count distinct variables, and will therefore e.g. return 3 even if two terms are actually the same variable.

Returns:

Since:

  • 0.3.0



254
255
256
257
258
259
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 254

def variable_count
  [subject, predicate, object, graph_name].inject(0) do |memo, term|
    memo += (term.is_a?(Variable) ? 1 :
             (term.is_a?(Pattern) ? term.variable_count : 0))
  end
end

#variable_terms(name = nil) ⇒ Array<Symbol>

Returns the variable terms in this pattern.

Examples:

Pattern.new(RDF::Node.new, :p, 123).variable_terms    #=> [:predicate]

Parameters:

  • name (Symbol, #to_sym) (defaults to: nil)

    an optional variable name

Returns:

Since:

  • 0.3.0



238
239
240
241
242
243
244
245
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 238

def variable_terms(name = nil)
  terms = []
  terms << :subject    if subject.is_a?(Variable)    && (!name || name.eql?(subject.name))
  terms << :predicate  if predicate.is_a?(Variable)  && (!name || name.eql?(predicate.name))
  terms << :object     if object.is_a?(Variable)     && (!name || name.eql?(object.name))
  terms << :graph_name if graph_name.is_a?(Variable) && (!name || name.eql?(graph_name.name))
  terms
end

#variablesHash{Symbol => Variable}

Returns all variables in this pattern.

Note: this returns a hash containing distinct variables only.

Returns:

Since:

  • 0.3.0



269
270
271
272
273
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/rdf-24ba7cdc342f/lib/rdf/query/pattern.rb', line 269

def variables
  [subject, predicate, object, graph_name].inject({}) do |memo, term|
    term && term.variable? ? memo.merge(term.variables) : memo
  end
end

#varsArray<RDF::Query::Variable>

Return the variables contained within this pattern



467
468
469
# File 'vendor/bundler/ruby/2.7.0/bundler/gems/sparql-cd4915d97d78/lib/sparql/algebra/extensions.rb', line 467

def vars
  variables.values
end