Class: RDF::Query
- Inherits:
-
Object
- Object
- RDF::Query
- Defined in:
- lib/rdf/query.rb,
lib/rdf/query/pattern.rb,
lib/rdf/query/solution.rb,
lib/rdf/query/variable.rb,
lib/rdf/query/solutions.rb,
lib/rdf/query/hash_pattern_normalizer.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.
Defined Under Namespace
Classes: HashPatternNormalizer, Pattern, Solution, Solutions, Variable
Instance Attribute Summary (collapse)
-
- (Hash) options
readonly
Any additional options for this query.
-
- (Array<RDF::Query::Pattern>) patterns
readonly
The patterns that constitute this query.
-
- (RDF::Query::Solutions) solutions
readonly
The solution sequence for this query.
-
- (Hash{Symbol => RDF::Query::Variable}) variables
readonly
The variables used in this query.
Class Method Summary (collapse)
-
+ (RDF::Query::Solutions) execute(queryable, patterns = nil, options = {}) {|query| ... }
Executes a query on the given
queryablegraph or repository.
Instance Method Summary (collapse)
-
- (RDF::Query) +(other)
Add patterns from another query to form a new Query.
-
- <<(pattern)
Appends the given query
patternto this query. -
- (RDF::IRI, RDF::Query::Variable) context
Scope of this query, if any.
-
- (RDF::IRI, RDF::Query::Variable) context=(value)
Scope the query to named graphs matching value.
-
- (Boolean) default?
Is this query scoped to the default graph?.
-
- (RDF::Query) dup
Duplicate query, including patterns and solutions.
-
- (Enumerator) each_solution {|solution| ... }
(also: #each)
Enumerates over each matching query solution.
-
- (Boolean) empty?
Query has no patterns.
-
- (RDF::Query::Solutions) execute(queryable, options = {})
Executes this query on the given
queryablegraph or repository. -
- (Boolean) failed?
Returns
trueif this query did not match when last executed. -
- (Query) initialize(*patterns, &block)
constructor
Initializes a new basic graph pattern query.
-
- (Boolean) matched?
Returns
trueif this query matched when last executed. -
- (Boolean) named?
Is this query scoped to a named graph?.
-
- (RDF::Query) optimize(options = {})
Returns an optimized copy of this query.
-
- optimize!(options = {})
Optimizes this query by reordering its constituent triple patterns according to their cost estimates.
-
- pattern(pattern, options = {})
Appends the given query
patternto this query. -
- (Boolean) unnamed?
Is this query unscoped? This indicates that it can return results from either a named graph or the default graph.
-
- validate!
Validate this query, making sure it can be executed by our query engine.
Constructor Details
- (Query) initialize(patterns = [], options = {}) {|query| ... } - (Query) initialize(patterns, options = {}) {|query| ... }
Initializes a new basic graph pattern query.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/rdf/query.rb', line 159 def initialize(*patterns, &block) @options = patterns.last.is_a?(Hash) ? patterns.pop.dup : {} patterns << @options if patterns.empty? @variables = {} @solutions = @options.delete(:solutions) || Solutions.new 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 |
Instance Attribute Details
- (Hash) options (readonly)
Any additional options for this query.
118 119 120 |
# File 'lib/rdf/query.rb', line 118 def @options end |
- (Array<RDF::Query::Pattern>) patterns (readonly)
The patterns that constitute this query.
106 107 108 |
# File 'lib/rdf/query.rb', line 106 def patterns @patterns end |
- (RDF::Query::Solutions) solutions (readonly)
The solution sequence for this query.
112 113 114 |
# File 'lib/rdf/query.rb', line 112 def solutions @solutions end |
- (Hash{Symbol => RDF::Query::Variable}) variables (readonly)
The variables used in this query.
100 101 102 |
# File 'lib/rdf/query.rb', line 100 def variables @variables end |
Class Method Details
+ (RDF::Query::Solutions) execute(queryable, patterns = nil, options = {}) {|query| ... }
Executes a query on the given queryable graph or repository.
92 93 94 |
# File 'lib/rdf/query.rb', line 92 def self.execute(queryable, patterns = nil, = {}, &block) self.new(patterns, , &block).execute(queryable, ) end |
Instance Method Details
- (RDF::Query) +(other)
Add patterns from another query to form a new Query
356 357 358 |
# File 'lib/rdf/query.rb', line 356 def +(other) Query.new(self.patterns + other.patterns) end |
- <<(pattern)
This method returns an undefined value.
Appends the given query pattern to this query.
190 191 192 193 |
# File 'lib/rdf/query.rb', line 190 def <<(pattern) @patterns << Pattern.from(pattern) self end |
- (RDF::IRI, RDF::Query::Variable) context
Scope of this query, if any
388 389 390 |
# File 'lib/rdf/query.rb', line 388 def context [:context] end |
- (RDF::IRI, RDF::Query::Variable) context=(value)
Scope the query to named graphs matching value
382 383 384 |
# File 'lib/rdf/query.rb', line 382 def context=(value) [:context] = value end |
- (Boolean) default?
Is this query scoped to the default graph?
368 369 370 |
# File 'lib/rdf/query.rb', line 368 def default? [:context] == false end |
- (RDF::Query) dup
Duplicate query, including patterns and solutions
412 413 414 415 416 |
# File 'lib/rdf/query.rb', line 412 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.
404 405 406 |
# File 'lib/rdf/query.rb', line 404 def each_solution(&block) @solutions.each(&block) end |
- (Boolean) empty?
Query has no patterns
394 395 396 |
# File 'lib/rdf/query.rb', line 394 def empty? patterns.empty? end |
- (RDF::Query::Solutions) execute(queryable, options = {})
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.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 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 |
# File 'lib/rdf/query.rb', line 262 def execute(queryable, = {}) validate! = .dup # just so we can call #keys below without worrying [: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 = [:solutions] || (Solutions.new << RDF::Query::Solution.new({})) patterns = @patterns context = .fetch(:context, .fetch(:name, self.context)) # Add context to pattern, if necessary unless context.nil? if patterns.empty? patterns = [Pattern.new(nil, nil, nil, :context => context)] elsif patterns.first.context.nil? patterns.first.context = context end end patterns.each do |pattern| old_solutions, @solutions = @solutions, Solutions.new [:bindings].keys.each do |variable| if pattern.variables.include?(variable) unbound_solutions, old_solutions = old_solutions, Solutions.new [:bindings][variable].each do |binding| unbound_solutions.each do |solution| old_solutions << solution.merge(variable => binding) end end [: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? # We have no solutions for variables we should have solutions for: if !pattern.optional? && pattern.variables.keys.any? { |variable| !@solutions.variable_names.include?(variable) } return Solutions.new end end @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.
337 338 339 |
# File 'lib/rdf/query.rb', line 337 def failed? @solutions.empty? 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.
349 350 351 |
# File 'lib/rdf/query.rb', line 349 def matched? !@failed end |
- (Boolean) named?
Is this query scoped to a named graph?
362 363 364 |
# File 'lib/rdf/query.rb', line 362 def named? !![:context] end |
- (RDF::Query) optimize(options = {})
Returns an optimized copy of this query.
217 218 219 |
# File 'lib/rdf/query.rb', line 217 def optimize( = {}) self.dup.optimize!() end |
- optimize!(options = {})
This method returns an undefined value.
Optimizes this query by reordering its constituent triple patterns according to their cost estimates.
230 231 232 233 234 235 |
# File 'lib/rdf/query.rb', line 230 def optimize!( = {}) @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.
205 206 207 208 |
# File 'lib/rdf/query.rb', line 205 def pattern(pattern, = {}) @patterns << Pattern.from(pattern, ) self end |
- (Boolean) unnamed?
Is this query unscoped? This indicates that it can return results from either a named graph or the default graph.
375 376 377 |
# File 'lib/rdf/query.rb', line 375 def unnamed? [:context].nil? end |
- validate!
This method returns an undefined value.
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.
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/rdf/query.rb', line 425 def validate! # Our first pattern, if it exists, cannot be an optional pattern. if @patterns.length > 0 && @patterns[0].optional? raise ArgumentError.new("Query must not begin with an optional pattern") end # All optional patterns must appear after the regular patterns. We # could test this more cleanly using Ruby 1.9-specific features, but # we want to run under Ruby 1.8, too. i = 0 i += 1 while i < @patterns.length && !@patterns[i].optional? while i < @patterns.length unless @patterns[i].optional? raise ArgumentError.new("Optional patterns must appear at end of query") end i += 1 end nil end |