class RDF::Virtuoso::Query
A SPARQL query builder.
@example Iterating over all found solutions
query.each_solution { |solution| puts solution.inspect }
Constants
- AGG_METHODS
SPARQL 1.1 Aggregates
@return [Query] @see www.w3.org/TR/sparql11-query/#defn_aggCount def count(*variables)
options[:count] = variables self
end
Attributes
@return [Symbol] @see www.w3.org/TR/rdf-sparql-query/#QueryForms
@return [Hash{Symbol => Object}]
@return [Array<[key, RDF::Value]>]
Public Class Methods
Creates a boolean ‘ASK` query.
@param [Hash{Symbol => Object}] options @return [Query] @see www.w3.org/TR/rdf-sparql-query/#ask
# File lib/rdf/virtuoso/query.rb, line 32 def self.ask(**options) self.new(:ask, **options) end
# File lib/rdf/virtuoso/query.rb, line 100 def self.clear(*variables, **options) self.new(:clear, **options).clear(variables.first) end
Creates a graph ‘CONSTRUCT` query.
@param [Array<RDF::Query::Pattern, Array>] patterns @param [Hash{Symbol => Object}] options @return [Query] @see www.w3.org/TR/rdf-sparql-query/#construct
# File lib/rdf/virtuoso/query.rb, line 65 def self.construct(*patterns, **options) self.new(:construct, **options).construct(*patterns) # FIXME end
# File lib/rdf/virtuoso/query.rb, line 92 def self.create(*variables, **options) self.new(:create, **options).create(variables.first) end
# File lib/rdf/virtuoso/query.rb, line 88 def self.delete(*patterns, **options) self.new(:delete, **options).delete(*patterns) end
# File lib/rdf/virtuoso/query.rb, line 84 def self.delete_data(*patterns, **options) self.new(:delete_data, **options).delete_data(*patterns) end
Creates a ‘DESCRIBE` query.
@param [Array<Symbol, RDF::URI>] variables @param [Hash{Symbol => Object}] options @return [Query] @see www.w3.org/TR/rdf-sparql-query/#describe
# File lib/rdf/virtuoso/query.rb, line 54 def self.describe(*variables, **options) self.new(:describe, **options).describe(*variables) end
# File lib/rdf/virtuoso/query.rb, line 96 def self.drop(*variables, **options) self.new(:drop, **options).drop(variables.first) end
# File lib/rdf/virtuoso/query.rb, line 80 def self.insert(*patterns, **options) self.new(:insert, **options).insert(*patterns) end
Creates an ‘UPDATE` query.
@param [Array<RDF::Query::Pattern, Array>] patterns @param [Hash{Symbol => Object}] options @return [Query] @see www.w3.org/Submission/SPARQL-Update/
# File lib/rdf/virtuoso/query.rb, line 76 def self.insert_data(*patterns, **options) self.new(:insert_data, **options).insert_data(*patterns) end
@param [Symbol, to_s
] form @param [Hash{Symbol => Object}] options @yield [query] @yieldparam [Query]
# File lib/rdf/virtuoso/query.rb, line 109 def initialize(form = :ask, **options, &block) @form = form.respond_to?(:to_sym) ? form.to_sym : form.to_s.to_sym super([], **options, &block) end
Creates a tuple ‘SELECT` query.
@param [Array<Symbol>] variables @param [Hash{Symbol => Object}] options @return [Query] @see www.w3.org/TR/rdf-sparql-query/#select
# File lib/rdf/virtuoso/query.rb, line 43 def self.select(*variables, **options) self.new(:select, **options).select(*variables) end
Public Instance Methods
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#ask
# File lib/rdf/virtuoso/query.rb, line 117 def ask @form = :ask self end
@private make RDF::Query::Pattern from triple array if not already done include :graph_name in Statement @return [RDF::Query::Pattern]
# File lib/rdf/virtuoso/query.rb, line 408 def build_patterns(patterns) patterns.map do |pattern| case pattern when RDF::Query::Pattern then pattern else RDF::Query::Pattern.new(*pattern.to_a) end end end
# File lib/rdf/virtuoso/query.rb, line 230 def clear(uri) options[:graph] = uri self end
@param [Array<RDF::Query::Pattern, Array>] patterns @return [Query] @see www.w3.org/TR/rdf-sparql-query/#construct
# File lib/rdf/virtuoso/query.rb, line 146 def construct(*patterns) new_patterns = [] patterns.each do |pattern| new_patterns << pattern.map do |value| if value.is_a?(Symbol) value = RDF::Query::Variable.new(value) elsif value.is_a?(RDF::URI) value = value else value = RDF::Literal.new(value) end end end @data_values = build_patterns(new_patterns) self end
# File lib/rdf/virtuoso/query.rb, line 220 def create(uri) options[:graph] = uri self end
@param string @return [Query] @see www.w3.org/TR/rdf-sparql-query/#specDataset
# File lib/rdf/virtuoso/query.rb, line 238 def define(string) options[:define] = string self end
# File lib/rdf/virtuoso/query.rb, line 203 def delete(*patterns) new_patterns = [] patterns.each do |pattern| new_patterns << pattern.map do |value| if value.is_a?(Symbol) value = RDF::Query::Variable.new(value) elsif value.is_a?(RDF::URI) value = value else value = RDF::Literal.new(value) end end end @data_values = build_patterns(new_patterns) self end
# File lib/rdf/virtuoso/query.rb, line 194 def delete_data(*patterns) new_patterns = [] patterns.each do |values| new_patterns << values.map { |var| [var, var.is_a?(RDF::URI) ? var : var] } end @data_values = new_patterns #build_patterns(new_patterns) self end
@param [Array<Symbol>] variables @return [Query] @see www.w3.org/TR/rdf-sparql-query/#describe
# File lib/rdf/virtuoso/query.rb, line 135 def describe(*variables) @values = variables.map { |var| [var, var.is_a?(RDF::URI) ? var : RDF::Query::Variable.new(var)] } self end
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#modDistinct
# File lib/rdf/virtuoso/query.rb, line 309 def distinct(state = true) options[:distinct] = state self end
# File lib/rdf/virtuoso/query.rb, line 225 def drop(uri) options[:graph] = uri self end
@yield [statement] @yieldparam [RDF::Statement] @return [Enumerator]
# File lib/rdf/virtuoso/query.rb, line 456 def each_statement(&block) result.each_statement(&block) end
@return [Boolean]
# File lib/rdf/virtuoso/query.rb, line 442 def false? !true? end
@private
# File lib/rdf/virtuoso/query.rb, line 419 def filter(string) (options[:filters] ||= []) << string self end
# File lib/rdf/virtuoso/query.rb, line 424 def filters(filters = nil) options[:filters] ||= [] options[:filters] += filters.to_a self end
@param [RDF::URI] uri @return [Query] @see www.w3.org/TR/rdf-sparql-query/#specDataset
# File lib/rdf/virtuoso/query.rb, line 246 def from(uri) options[:from] = uri self end
@param [RDF::URI] uri @return [Query]
# File lib/rdf/virtuoso/query.rb, line 253 def from_named(uri) (options[:from_named] ||= []) << uri self end
@param [RDF::URI] uri @return [Query]
# File lib/rdf/virtuoso/query.rb, line 260 def graph(uri) options[:graph] = uri self end
@param [RDF::URI] uri @return [Query] Inline version of graph
# File lib/rdf/virtuoso/query.rb, line 290 def graph2(uri) @patterns += [Pattern.new(:graph_statement, uri)] self end
@param [Array<RDF::Query::Pattern, Array>] patterns @return [Query] Group is a non-SPARQL function. It works same as where, but groups the patterns within brackets: { }, allowing to structure the query.
# File lib/rdf/virtuoso/query.rb, line 281 def group(*patterns) @patterns += [Pattern.new(:start_group_pattern)] + build_patterns(patterns) + [Pattern.new(:end_group_pattern)] self end
# File lib/rdf/virtuoso/query.rb, line 177 def insert(*patterns) new_patterns = [] patterns.each do |pattern| new_patterns << pattern.map do |value| if value.is_a?(Symbol) value = RDF::Query::Variable.new(value) elsif value.is_a?(RDF::URI) value = value else value = RDF::Literal.new(value) end end end @data_values = build_patterns(new_patterns) self end
@param [Array<RDF::Query::Pattern, Array>] patterns @return [Query] @see www.w3.org/Submission/SPARQL-Update/
# File lib/rdf/virtuoso/query.rb, line 168 def insert_data(*patterns) new_patterns = [] patterns.each do |values| new_patterns << values.map { |var| [var, var.is_a?(RDF::URI) ? var : var] } end @data_values = new_patterns #build_patterns(new_patterns) self end
Returns a developer-friendly representation of this query.
@return [String]
# File lib/rdf/virtuoso/query.rb, line 706 def inspect sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, to_s) end
Outputs a developer-friendly representation of this query to ‘stderr`.
@return [void]
# File lib/rdf/virtuoso/query.rb, line 697 def inspect! warn(inspect) self end
@param [Integer, to_i] length @return [Query] @see www.w3.org/TR/rdf-sparql-query/#modResultLimit
# File lib/rdf/virtuoso/query.rb, line 351 def limit(length) slice(nil, length) end
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#minus
# File lib/rdf/virtuoso/query.rb, line 393 def minus(*patterns) (options[:minuses] ||= []) << build_patterns(patterns) self end
@param [Integer, to_i] start @return [Query] @see www.w3.org/TR/rdf-sparql-query/#modOffset
# File lib/rdf/virtuoso/query.rb, line 343 def offset(start) slice(start, nil) end
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#optionals
# File lib/rdf/virtuoso/query.rb, line 385 def optional(*patterns) (options[:optionals] ||= []) << build_patterns(patterns) self end
@param [Array<Symbol, String>] variables @return [Query] @see www.w3.org/TR/rdf-sparql-query/#modOrderBy
# File lib/rdf/virtuoso/query.rb, line 299 def order(*variables) options[:order_by] = variables self end
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#prefNames
# File lib/rdf/virtuoso/query.rb, line 368 def prefix(string) (options[:prefixes] ||= []) << string self end
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#prefNames
# File lib/rdf/virtuoso/query.rb, line 376 def prefixes(prefixes = nil) options[:prefixes] ||= [] options[:prefixes] += prefixes.to_a self end
@return [Query] @see www.w3.org/TR/rdf-sparql-query/#modReduced
# File lib/rdf/virtuoso/query.rb, line 317 def reduced(state = true) options[:reduced] = state self end
@return [Object]
# File lib/rdf/virtuoso/query.rb, line 462 def result @result ||= execute end
@param [Array<Symbol>] variables @return [Query] @see www.w3.org/TR/rdf-sparql-query/#select
# File lib/rdf/virtuoso/query.rb, line 126 def select(*variables) @values = variables.map { |var| [var, RDF::Query::Variable.new(var)] } self end
@private
# File lib/rdf/virtuoso/query.rb, line 675 def serialize_patterns(patterns) if patterns.is_a?(RDF::Query::Pattern) if patterns.variables[:start_group_pattern] "{" elsif patterns.variables[:end_group_pattern] "}" elsif patterns.variables[:graph_statement] "GRAPH #{serialize_value(patterns[1])}" else patterns.to_triple.map { |v| serialize_value(v) }.join(' ') << " ." end else patterns.map do |p| p.to_triple.map { |v| serialize_value(v) }.join(' ') << " ." end end end
Serializes an RDF::Value into a format appropriate for select, construct, and where clauses
@param [RDF::Value] value @return [String] @private
# File lib/rdf/virtuoso/query.rb, line 716 def serialize_value(value) # SPARQL queries are UTF-8, but support ASCII-style Unicode escapes, so # the N-Triples serializer is fine unless it's a variable: case when value.is_a?(String) then value.inspect when value.is_a?(RDF::Query::Variable) then value.to_s else RDF::NTriples.serialize(value) end end
@param [Integer, to_i] start @param [Integer, to_i] length @return [Query]
# File lib/rdf/virtuoso/query.rb, line 359 def slice(start, length) options[:offset] = start.to_i if start options[:limit] = length.to_i if length self end
@return [Enumerable<RDF::Query::Solution>]
# File lib/rdf/virtuoso/query.rb, line 448 def solutions result end
Returns the string representation of this query.
@return [String]
# File lib/rdf/virtuoso/query.rb, line 477 def to_s buffer = [] buffer << "DEFINE #{options[:define]}" if options[:define] buffer << [form.to_s.gsub('_', ' ').upcase] case form when :select, :describe buffer << 'DISTINCT' if options[:distinct] buffer << 'REDUCED' if options[:reduced] # Aggregates in select/describe aggregates = [:count, :min, :max, :avg, :sum, :sample, :group_concat, :group_digest] if (options.keys & aggregates).any? (options.keys & aggregates).each do |agg| case agg when :sample # multiple samples splits to individual sample expressions options[agg].each_slice(1) do |a| buffer << '(sql:' + agg.to_s.upcase a.map do |var| buffer << (var.is_a?(String) ? var : "(?#{var})") buffer << "AS ?#{var})" end end when :group_concat # multiple samples splits to individual sample expressions options[agg].each_slice(2) do |a| buffer << '(sql:' + agg.to_s.upcase buffer << a.map {|var| (var.is_a?(Symbol) ? "(?#{var}" : var.is_a?(String) ? "'#{var}'" : var )}.join(', ') buffer << ') AS ?' + a.first.to_s + ')' end when :group_digest # multiple samples splits to individual sample expressions options[agg].each_slice(4) do |a| buffer << '(sql:' + agg.to_s.upcase buffer << a.map {|var| (var.is_a?(Symbol) ? "(?#{var}" : var.is_a?(String) ? "'#{var}'" : var )}.join(', ') buffer << ') AS ?' + a.first.to_s + ')' end else # multiple samples splits to individual sample expressions options[agg].each_slice(1) do |a| buffer << '(' + agg.to_s.upcase a.map do |var| buffer << (var.is_a?(String) ? var : "(?#{var})") buffer << "AS ?#{var})" end end end # end # also handle variables that are not aggregates buffer << values.map { |v| serialize_value(v[1]) }.join(' ') unless values.empty? else # no variables? select/describe all (*) buffer << (values.empty? ? '*' : values.map { |v| serialize_value(v[1]) }.join(' ')) end when :construct buffer << '{' buffer += serialize_patterns(@data_values) buffer << '}' # for virtuoso inserts when :insert_data buffer << "INTO GRAPH #{serialize_value(options[:graph])}" if options[:graph] buffer << '{' @data_values.each do |triple| if triple.first.first.is_a?(RDF::Statement) buffer << triple.map { |v| serialize_value(v[1])} else buffer << triple.map { |v| serialize_value(v[1])}.join(' ') + " ." end end buffer << '}' when :insert buffer << "INTO GRAPH #{serialize_value(options[:graph])}" if options[:graph] # buffer += serialize_patterns(options[:template]) # (@data_values.map { |v| puts v[1].inspect; puts 'xxx ' } ) buffer << '{' buffer += serialize_patterns(@data_values) buffer << '}' when :delete_data buffer << "FROM #{serialize_value(options[:graph])}" if options[:graph] buffer << '{' @data_values.each do |triple| if triple.first.first.is_a?(RDF::Statement) buffer << triple.map { |v| serialize_value(v[1])} else buffer << triple.map { |v| serialize_value(v[1])}.join(' ') + " ." end end buffer << '}' when :delete buffer << "FROM #{serialize_value(options[:graph])}" if options[:graph] buffer << '{' buffer += serialize_patterns(@data_values) buffer << '}' when :create, :drop buffer << 'SILENT' if options[:silent] buffer << "GRAPH #{serialize_value(options[:graph])}" when :clear buffer << "GRAPH #{serialize_value(options[:graph])}" end buffer << "FROM #{serialize_value(options[:from])}" if options[:from] options[:from_named].each {|from_named| buffer << "FROM NAMED #{serialize_value(from_named)}" } if options[:from_named] unless patterns.empty? && ([:describe, :insert_data, :delete_data, :create, :clear, :drop].include?(form)) buffer << 'WHERE {' buffer << '{' if options[:unions] # iterate patterns # does patterns have :graph_name hash? build with GRAPH statement patterns.each do | pattern| if pattern.graph_name buffer << "GRAPH #{serialize_value(RDF::URI(pattern.graph_name))}" buffer << '{' buffer << serialize_patterns(pattern) buffer << '}' else buffer << serialize_patterns(pattern) end end if options[:optionals] options[:optionals].each do |patterns| buffer << 'OPTIONAL {' patterns.each do | pattern| if pattern.graph_name buffer << "GRAPH #{serialize_value(RDF::URI(pattern.graph_name))}" buffer << '{' buffer << serialize_patterns(pattern) buffer << '}' else buffer << serialize_patterns(pattern) end end buffer << '}' end end if options[:minuses] options[:minuses].each do |patterns| buffer << 'MINUS {' patterns.each do | pattern| if pattern.graph_name buffer << "GRAPH #{serialize_value(RDF::URI(pattern.graph_name))}" buffer << '{' buffer << serialize_patterns(pattern) buffer << '}' else buffer << serialize_patterns(pattern) end end buffer << '}' end end if options[:filters] buffer += options[:filters].map { |filter| "FILTER(#{filter})" } end buffer << '}' if options[:unions] options[:unions].each do |patterns| buffer << 'UNION {' buffer += serialize_patterns(patterns) buffer << '}' end buffer << '}' end end if options[:order_by] buffer << 'ORDER BY' buffer += options[:order_by].map { |var| var.is_a?(String) ? var : "?#{var}" } end buffer << "OFFSET #{options[:offset]}" if options[:offset] buffer << "LIMIT #{options[:limit]}" if options[:limit] options[:prefixes].reverse.each {|e| buffer.unshift("PREFIX #{e}") } if options[:prefixes] buffer.join(' ') end
@return [Boolean]
# File lib/rdf/virtuoso/query.rb, line 432 def true? case result when TrueClass, FalseClass then result when Enumerable then !result.empty? else false end end
# File lib/rdf/virtuoso/query.rb, line 398 def union(*patterns) (options[:unions] ||= []) << build_patterns(patterns) self end
@param [Array<RDF::Query::Pattern, Array>] patterns @return [Query] @see www.w3.org/TR/rdf-sparql-query/#GraphPattern
# File lib/rdf/virtuoso/query.rb, line 269 def where(*patterns) @patterns += build_patterns(patterns) self end