Class: RDF::Query::Pattern
- Defined in:
- lib/rdf/query/pattern.rb
Overview
An RDF query pattern.
Instance Attribute Summary collapse
-
#cost ⇒ Numeric
The estimated cost of this pattern (for query optimization).
-
#options ⇒ Hash
readonly
Any additional options for this pattern.
Attributes inherited from Statement
#graph_name, #id, #object, #predicate, #subject
Class Method Summary collapse
Instance Method Summary collapse
-
#bind(solution) ⇒ self
Binds the pattern to a solution, making it no longer variable if all variables are resolved to bound variables.
-
#binding_count ⇒ Integer
Returns the number of bindings in this pattern.
-
#bindings ⇒ Hash{Symbol => RDF::Term}
Returns all bindings in this pattern.
-
#bindings? ⇒ Boolean
Returns ‘true` if this pattern contains bindings.
-
#blank? ⇒ Boolean
Returns ‘true` if this is a blank pattern, with all terms being `nil`.
-
#bound? ⇒ Boolean
Returns ‘true` if all variables in this pattern are bound.
-
#bound_variables ⇒ Hash{Symbol => Variable}
Returns all bound variables in this pattern.
-
#execute(queryable, bindings = {}) {|statement| ... } ⇒ Enumerable<RDF::Query::Pattern>
Executes this query pattern on the given ‘queryable` object.
-
#has_variables? ⇒ Boolean
(also: #variables?)
Returns ‘true` if this pattern contains any variables.
-
#initialize(subject = nil, predicate = nil, object = nil, options = {}) ⇒ Pattern
constructor
A new instance of Pattern.
- #initialize! ⇒ Object
-
#optional? ⇒ Boolean
Returns ‘true` if this is an optional pattern.
-
#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`.
-
#to_s ⇒ String
Returns a string representation of this pattern.
-
#unbound? ⇒ Boolean
Returns ‘true` if all variables in this pattern are unbound.
-
#unbound_variables ⇒ Hash{Symbol => Variable}
Returns all unbound variables in this pattern.
-
#valid? ⇒ Boolean
Is this pattern composed only of valid components?.
-
#variable_count ⇒ Integer
(also: #cardinality, #arity)
Returns the number of variables in this pattern.
-
#variable_terms(name = nil) ⇒ Array<Symbol>
Returns the variable terms in this pattern.
-
#variables ⇒ Hash{Symbol => Variable}
Returns all variables in this pattern.
Methods inherited from Statement
#==, #===, #[], #[]=, #asserted?, #canonicalize, #canonicalize!, #complete?, #eql?, #has_graph?, #has_object?, #has_predicate?, #has_subject?, #incomplete?, #inferred?, #invalid?, #node?, #quoted?, #reified, #statement?, #to_hash, #to_quad, #to_triple, #variable?
Methods included from Value
#anonymous?, #canonicalize, #canonicalize!, #constant?, #graph?, #inspect, #inspect!, #invalid?, #iri?, #list?, #literal?, #node?, #resource?, #statement?, #term?, #to_nquads, #to_ntriples, #to_rdf, #to_term, #type_error, #uri?, #validate!, #variable?
Constructor Details
#initialize(options = {}) ⇒ Pattern #initialize(subject, predicate, object, options = {}) ⇒ Pattern
Statement treats symbols as interned Node instances, in a RDF::Query::Pattern, they are treated as Variable.
Returns a new instance of Pattern.
38 39 40 |
# File 'lib/rdf/query/pattern.rb', line 38 def initialize(subject = nil, predicate = nil, object = nil, = {}) super end |
Instance Attribute Details
#cost ⇒ Numeric
The estimated cost of this pattern (for query optimization).
62 63 64 |
# File 'lib/rdf/query/pattern.rb', line 62 def cost @cost end |
#options ⇒ Hash (readonly)
Any additional options for this pattern.
56 57 58 |
# File 'lib/rdf/query/pattern.rb', line 56 def @options end |
Class Method Details
.from(pattern, options = {}) ⇒ Object
8 9 10 11 12 13 14 15 16 |
# File 'lib/rdf/query/pattern.rb', line 8 def self.from(pattern, = {}) case pattern when Pattern then pattern when Array, Statement self.new(pattern[0], pattern[1], pattern[2], .merge(graph_name: pattern[3])) when Hash then self.new(.merge(pattern)) else raise ArgumentError, "expected RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}" end 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
253 254 255 256 257 258 259 260 |
# File 'lib/rdf/query/pattern.rb', line 253 def bind(solution) self.to_quad.each_with_index do |term, index| if term && term.variable? && solution[term] self[index] = solution[term] end end self end |
#binding_count ⇒ Integer
Returns the number of bindings in this pattern.
274 275 276 |
# File 'lib/rdf/query/pattern.rb', line 274 def binding_count bindings.size end |
#bindings ⇒ Hash{Symbol => RDF::Term}
Returns all bindings in this pattern.
282 283 284 285 286 287 288 289 |
# File 'lib/rdf/query/pattern.rb', line 282 def bindings bindings = {} bindings.merge!(subject.bindings) if subject.is_a?(Variable) bindings.merge!(predicate.bindings) if predicate.is_a?(Variable) bindings.merge!(object.bindings) if object.is_a?(Variable) bindings.merge!(graph_name.bindings) if graph_name.is_a?(Variable) bindings end |
#bindings? ⇒ Boolean
Returns ‘true` if this pattern contains bindings.
266 267 268 |
# File 'lib/rdf/query/pattern.rb', line 266 def bindings? !bindings.empty? end |
#blank? ⇒ Boolean
Returns ‘true` if this is a blank pattern, with all terms being `nil`.
69 70 71 |
# File 'lib/rdf/query/pattern.rb', line 69 def blank? subject.nil? && predicate.nil? && object.nil? && graph_name.nil? end |
#bound? ⇒ Boolean
Returns ‘true` if all variables in this pattern are bound.
295 296 297 |
# File 'lib/rdf/query/pattern.rb', line 295 def bound? !variables.empty? && variables.values.all?(&:bound?) end |
#bound_variables ⇒ Hash{Symbol => Variable}
Returns all bound variables in this pattern.
303 304 305 |
# File 'lib/rdf/query/pattern.rb', line 303 def bound_variables variables.reject { |name, variable| variable.unbound? } 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`.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rdf/query/pattern.rb', line 137 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.
78 79 80 81 82 83 |
# File 'lib/rdf/query/pattern.rb', line 78 def has_variables? subject.is_a?(Variable) || predicate.is_a?(Variable) || object.is_a?(Variable) || graph_name.is_a?(Variable) end |
#initialize! ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/rdf/query/pattern.rb', line 44 def initialize! @graph_name = Variable.new(@graph_name) if @graph_name.is_a?(Symbol) @subject = Variable.new(@subject) if @subject.is_a?(Symbol) @predicate = Variable.new(@predicate) if @predicate.is_a?(Symbol) @object = Variable.new(@object) if @object.is_a?(Symbol) super end |
#optional? ⇒ Boolean
Returns ‘true` if this is an optional pattern.
95 96 97 |
# File 'lib/rdf/query/pattern.rb', line 95 def optional? !![: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`.
187 188 189 190 191 192 193 194 |
# File 'lib/rdf/query/pattern.rb', line 187 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) end end |
#to_s ⇒ String
Returns a string representation of this pattern.
327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/rdf/query/pattern.rb', line 327 def to_s StringIO.open do |buffer| # FIXME in RDF::Statement buffer << 'OPTIONAL ' if optional? buffer << [subject, predicate, object].map do |r| r.is_a?(RDF::Query::Variable) ? r.to_s : RDF::NTriples.serialize(r) 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 |
#unbound? ⇒ Boolean
Returns ‘true` if all variables in this pattern are unbound.
311 312 313 |
# File 'lib/rdf/query/pattern.rb', line 311 def unbound? !variables.empty? && variables.values.all?(&:unbound?) end |
#unbound_variables ⇒ Hash{Symbol => Variable}
Returns all unbound variables in this pattern.
319 320 321 |
# File 'lib/rdf/query/pattern.rb', line 319 def unbound_variables variables.reject { |name, variable| variable.bound? } end |
#valid? ⇒ Boolean
Is this pattern composed only of valid components?
103 104 105 106 107 108 109 110 |
# File 'lib/rdf/query/pattern.rb', line 103 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_count ⇒ Integer 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.
222 223 224 225 226 227 228 229 |
# File 'lib/rdf/query/pattern.rb', line 222 def variable_count count = 0 count += 1 if subject.is_a?(Variable) count += 1 if predicate.is_a?(Variable) count += 1 if object.is_a?(Variable) count += 1 if graph_name.is_a?(Variable) count end |
#variable_terms(name = nil) ⇒ Array<Symbol>
Returns the variable terms in this pattern.
206 207 208 209 210 211 212 213 |
# File 'lib/rdf/query/pattern.rb', line 206 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 |
#variables ⇒ Hash{Symbol => Variable}
Returns all variables in this pattern.
Note: this returns a hash containing distinct variables only.
239 240 241 242 243 244 245 246 |
# File 'lib/rdf/query/pattern.rb', line 239 def variables variables = {} variables.merge!(subject.variables) if subject.is_a?(Variable) variables.merge!(predicate.variables) if predicate.is_a?(Variable) variables.merge!(object.variables) if object.is_a?(Variable) variables.merge!(graph_name.variables) if graph_name.is_a?(Variable) variables end |