Skip to content

Commit 5f45c98

Browse files
committed
Deprecate Query::Pattern#variable_names. Add #var_values and Query::Pattern#var_values to return the appropriate value from a statement (including embedding) associated with that value. This abstracts pattern matching to allow for embedded statements, and other things that can be used in a pattern (e.g., lists).
1 parent 8db27b2 commit 5f45c98

4 files changed

Lines changed: 195 additions & 47 deletions

File tree

lib/rdf/query/pattern.rb

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,10 @@ def execute(queryable, bindings = {}, &block)
181181

182182
# No, some terms actually refer to the same variable...
183183
else
184-
# Figure out which terms refer to the same variable:
185-
terms = variables.each_key.find do |name|
186-
terms = variable_terms(name)
187-
break terms if terms.size > 1
188-
end
184+
# Considering embedding, figure out if variables that may appear more than once resolve to the same value.
185+
vars = variables.keys
189186
queryable.query(query).select do |statement|
190-
# Only yield those matching statements where the variable
191-
# constraint is also satisfied:
192-
# FIXME: `Array#uniq` uses `#eql?` and `#hash`, not `#==`
193-
if terms.map { |term| statement.send(term) }.uniq.size.equal?(1)
187+
if vars.all? {|var| self.var_values(var, statement).uniq.size == 1}
194188
yield statement if block_given?
195189
true
196190
end
@@ -220,8 +214,8 @@ def solution(statement)
220214
solution[predicate.to_sym] = statement.predicate if predicate.is_a?(Variable)
221215
solution[object.to_sym] = statement.object if object.is_a?(Variable)
222216
solution[graph_name.to_sym] = statement.graph_name if graph_name.is_a?(Variable)
223-
solution.merge!(subject.solution(statement.subject)) if subject.is_a?(Pattern)
224-
solution.merge!(object.solution(statement.object)) if object.is_a?(Pattern)
217+
solution.merge!(subject.solution(statement.subject)) if subject.respond_to?(:solution)
218+
solution.merge!(object.solution(statement.object)) if object.respond_to?(:solution)
225219
end
226220
end
227221

@@ -234,8 +228,11 @@ def solution(statement)
234228
# @param [Symbol, #to_sym] name
235229
# an optional variable name
236230
# @return [Array<Symbol>]
231+
# @deprecated use {#var_values} instead
237232
# @since 0.3.0
238233
def variable_terms(name = nil)
234+
warn "[DEPRECATION] RDF::Query::Pattern#variable_terms is deprecated and will be removed in a future version.\n" +
235+
"Called from #{Gem.location_of_caller.join(':')}"
239236
terms = []
240237
terms << :subject if subject.is_a?(Variable) && (!name || name.eql?(subject.name))
241238
terms << :predicate if predicate.is_a?(Variable) && (!name || name.eql?(predicate.name))
@@ -244,6 +241,20 @@ def variable_terms(name = nil)
244241
terms
245242
end
246243

244+
##
245+
# Returns all values the statement in the same pattern position
246+
#
247+
# @param [Symbol] var
248+
# @param [RDF::Statement] statement
249+
# @return [Array<RDF::Term>]
250+
def var_values(var, statement)
251+
[:subject, :predicate, :object, :graph_name].map do |position|
252+
po = self.send(position)
253+
so = statement.send(position)
254+
po.var_values(var, so) if po.respond_to?(:var_values)
255+
end.flatten.compact
256+
end
257+
247258
##
248259
# Returns the number of variables in this pattern.
249260
#
@@ -254,7 +265,7 @@ def variable_terms(name = nil)
254265
def variable_count
255266
[subject, predicate, object, graph_name].inject(0) do |memo, term|
256267
memo += (term.is_a?(Variable) ? 1 :
257-
(term.is_a?(Pattern) ? term.variable_count : 0))
268+
(term.respond_to?(:variable_count) ? term.variable_count : 0))
258269
end
259270
end
260271
alias_method :cardinality, :variable_count
@@ -311,9 +322,9 @@ def binding_count
311322
def bindings
312323
bindings = {}
313324
bindings.merge!(subject.bindings) if subject && subject.variable?
314-
bindings.merge!(predicate.bindings) if predicate.is_a?(Variable)
325+
bindings.merge!(predicate.bindings) if predicate && predicate.variable?
315326
bindings.merge!(object.bindings) if object && object.variable?
316-
bindings.merge!(graph_name.bindings) if graph_name.is_a?(Variable)
327+
bindings.merge!(graph_name.bindings) if graph_name && graph_name.variable?
317328
bindings
318329
end
319330

@@ -354,24 +365,7 @@ def unbound_variables
354365
#
355366
# @return [String]
356367
def to_s
357-
StringIO.open do |buffer| # FIXME in RDF::Statement
358-
buffer << 'OPTIONAL ' if optional?
359-
buffer << [subject, predicate, object].map do |r|
360-
if r.is_a?(RDF::Query::Variable)
361-
r.to_s
362-
elsif r.is_a?(RDF::Query::Pattern)
363-
"<<#{r.to_s[0..-3]}>>"
364-
else
365-
RDF::NTriples.serialize(r)
366-
end
367-
end.join(" ")
368-
buffer << case graph_name
369-
when nil, false then " ."
370-
when Variable then " #{graph_name.to_s} ."
371-
else " #{RDF::NTriples.serialize(graph_name)} ."
372-
end
373-
buffer.string
374-
end
368+
(optional? ? 'OPTIONAL ' : '') + super
375369
end
376370
end # Pattern
377371
end; end # RDF::Query

lib/rdf/query/variable.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,16 @@ def ===(other)
246246
end
247247
end
248248

249+
##
250+
# Returns term if var is the same as this variable.
251+
#
252+
# @param [Symbol] var
253+
# @param [RDF::Term] term
254+
# @return [RDF::Term]
255+
def var_values(var, term)
256+
term if var == name
257+
end
258+
249259
##
250260
# Returns a string representation of this variable.
251261
#

0 commit comments

Comments
 (0)