Module: SPARQL

Defined in:
lib/sparql.rb,
lib/sparql/server.rb,
lib/sparql/algebra.rb,
lib/sparql/grammar.rb,
lib/sparql/results.rb,
lib/sparql/version.rb,
lib/sparql/algebra/query.rb,
lib/sparql/algebra/update.rb,
lib/sparql/algebra/version.rb,
lib/sparql/algebra/operator.rb,
lib/sparql/algebra/aggregate.rb,
lib/sparql/algebra/expression.rb,
lib/sparql/algebra/evaluatable.rb,
lib/sparql/algebra/operator/if.rb,
lib/sparql/algebra/operator/in.rb,
lib/sparql/algebra/operator/or.rb,
lib/sparql/algebra/operator/tz.rb,
lib/sparql/algebra/operator/abs.rb,
lib/sparql/algebra/operator/add.rb,
lib/sparql/algebra/operator/alt.rb,
lib/sparql/algebra/operator/and.rb,
lib/sparql/algebra/operator/asc.rb,
lib/sparql/algebra/operator/ask.rb,
lib/sparql/algebra/operator/avg.rb,
lib/sparql/algebra/operator/bgp.rb,
lib/sparql/algebra/operator/day.rb,
lib/sparql/algebra/operator/iri.rb,
lib/sparql/algebra/operator/max.rb,
lib/sparql/algebra/operator/md5.rb,
lib/sparql/algebra/operator/min.rb,
lib/sparql/algebra/operator/not.rb,
lib/sparql/algebra/operator/now.rb,
lib/sparql/algebra/operator/seq.rb,
lib/sparql/algebra/operator/str.rb,
lib/sparql/algebra/operator/sum.rb,
lib/sparql/algebra/operator/base.rb,
lib/sparql/algebra/operator/ceil.rb,
lib/sparql/algebra/operator/copy.rb,
lib/sparql/algebra/operator/desc.rb,
lib/sparql/algebra/operator/drop.rb,
lib/sparql/algebra/operator/join.rb,
lib/sparql/algebra/operator/lang.rb,
lib/sparql/algebra/operator/load.rb,
lib/sparql/algebra/operator/move.rb,
lib/sparql/algebra/operator/path.rb,
lib/sparql/algebra/operator/plus.rb,
lib/sparql/algebra/operator/rand.rb,
lib/sparql/algebra/operator/sha1.rb,
lib/sparql/algebra/operator/uuid.rb,
lib/sparql/algebra/operator/with.rb,
lib/sparql/algebra/operator/year.rb,
lib/sparql/algebra/operator/bnode.rb,
lib/sparql/algebra/operator/bound.rb,
lib/sparql/algebra/operator/clear.rb,
lib/sparql/algebra/operator/count.rb,
lib/sparql/algebra/operator/equal.rb,
lib/sparql/algebra/operator/floor.rb,
lib/sparql/algebra/operator/graph.rb,
lib/sparql/algebra/operator/group.rb,
lib/sparql/algebra/operator/hours.rb,
lib/sparql/algebra/operator/lcase.rb,
lib/sparql/algebra/operator/minus.rb,
lib/sparql/algebra/operator/month.rb,
lib/sparql/algebra/operator/notin.rb,
lib/sparql/algebra/operator/order.rb,
lib/sparql/algebra/operator/regex.rb,
lib/sparql/algebra/operator/round.rb,
lib/sparql/algebra/operator/slice.rb,
lib/sparql/algebra/operator/strdt.rb,
lib/sparql/algebra/operator/table.rb,
lib/sparql/algebra/operator/ucase.rb,
lib/sparql/algebra/operator/union.rb,
lib/sparql/algebra/operator/using.rb,
lib/sparql/algebra/operator/adjust.rb,
lib/sparql/algebra/operator/concat.rb,
lib/sparql/algebra/operator/create.rb,
lib/sparql/algebra/operator/delete.rb,
lib/sparql/algebra/operator/divide.rb,
lib/sparql/algebra/operator/exists.rb,
lib/sparql/algebra/operator/extend.rb,
lib/sparql/algebra/operator/filter.rb,
lib/sparql/algebra/operator/insert.rb,
lib/sparql/algebra/operator/is_iri.rb,
lib/sparql/algebra/operator/modify.rb,
lib/sparql/algebra/operator/negate.rb,
lib/sparql/algebra/operator/object.rb,
lib/sparql/algebra/operator/prefix.rb,
lib/sparql/algebra/operator/sample.rb,
lib/sparql/algebra/operator/sha256.rb,
lib/sparql/algebra/operator/sha384.rb,
lib/sparql/algebra/operator/sha512.rb,
lib/sparql/algebra/operator/strlen.rb,
lib/sparql/algebra/operator/substr.rb,
lib/sparql/algebra/operator/triple.rb,
lib/sparql/algebra/operator/update.rb,
lib/sparql/algebra/operator/compare.rb,
lib/sparql/algebra/operator/dataset.rb,
lib/sparql/algebra/operator/minutes.rb,
lib/sparql/algebra/operator/project.rb,
lib/sparql/algebra/operator/reduced.rb,
lib/sparql/algebra/operator/replace.rb,
lib/sparql/algebra/operator/reverse.rb,
lib/sparql/algebra/operator/seconds.rb,
lib/sparql/algebra/operator/service.rb,
lib/sparql/algebra/operator/strends.rb,
lib/sparql/algebra/operator/strlang.rb,
lib/sparql/algebra/operator/struuid.rb,
lib/sparql/algebra/operator/subject.rb,
lib/sparql/algebra/operator/coalesce.rb,
lib/sparql/algebra/operator/contains.rb,
lib/sparql/algebra/operator/datatype.rb,
lib/sparql/algebra/operator/describe.rb,
lib/sparql/algebra/operator/distinct.rb,
lib/sparql/algebra/operator/exprlist.rb,
lib/sparql/algebra/operator/is_blank.rb,
lib/sparql/algebra/operator/multiply.rb,
lib/sparql/algebra/operator/notoneof.rb,
lib/sparql/algebra/operator/path_opt.rb,
lib/sparql/algebra/operator/sequence.rb,
lib/sparql/algebra/operator/strafter.rb,
lib/sparql/algebra/operator/subtract.rb,
lib/sparql/algebra/operator/timezone.rb,
lib/sparql/algebra/operator/construct.rb,
lib/sparql/algebra/operator/is_triple.rb,
lib/sparql/algebra/operator/left_join.rb,
lib/sparql/algebra/operator/less_than.rb,
lib/sparql/algebra/operator/not_equal.rb,
lib/sparql/algebra/operator/notexists.rb,
lib/sparql/algebra/operator/path_plus.rb,
lib/sparql/algebra/operator/path_star.rb,
lib/sparql/algebra/operator/path_zero.rb,
lib/sparql/algebra/operator/predicate.rb,
lib/sparql/algebra/operator/same_term.rb,
lib/sparql/algebra/operator/strbefore.rb,
lib/sparql/algebra/operator/strstarts.rb,
lib/sparql/algebra/operator/is_literal.rb,
lib/sparql/algebra/operator/is_numeric.rb,
lib/sparql/algebra/operator/path_range.rb,
lib/sparql/algebra/operator/delete_data.rb,
lib/sparql/algebra/operator/insert_data.rb,
lib/sparql/algebra/operator/delete_where.rb,
lib/sparql/algebra/operator/greater_than.rb,
lib/sparql/algebra/operator/group_concat.rb,
lib/sparql/algebra/operator/lang_matches.rb,
lib/sparql/algebra/operator/function_call.rb,
lib/sparql/algebra/operator/encode_for_uri.rb,
lib/sparql/algebra/operator/less_than_or_equal.rb,
lib/sparql/algebra/operator/greater_than_or_equal.rb

Overview

A SPARQL for RDF.rb.

Defined Under Namespace

Modules: Algebra, Grammar, Results, Server, VERSION Classes: MalformedQuery, QueryRequestRefused

Constant Summary collapse

ERROR_MESSAGE =
%q(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>SPARQL Processing Service: %s</title>
  </head>
  <body>
    <p>%s: %s</p>
  </body>
</html>
).freeze

Class Method Summary collapse

Class Method Details

.execute(query, queryable, **options) {|solution| ... } ⇒ RDF::Graph, ...

Parse and execute the given SPARQL query string against queriable.

Requires a queryable object (such as an RDF::Repository), into which the dataset will be loaded.

Optionally takes a list of URIs to load as default or named graphs into queryable.

Note, if default or named graphs are specified as options (protocol elements), or the query references specific default or named graphs the graphs are either presumed to be existant in queryable or are loaded into queryable depending on the presense and value of the :load_datasets option.

Attempting to load into an immutable queryable will result in a TypeError.

Examples:

repository = RDF::Repository.new
results = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)

Parameters:

Options Hash (**options):

  • :optimize (Boolean)

    Optimize query before execution.

  • :default_graph_uri (RDF::URI, String, Array<RDF::URI, String>)
  • :load_datasets (RDF::URI, String, Array<RDF::URI, String>)

    One or more URIs used to initialize a new instance of queryable in the default graph. One or more URIs used to initialize a new instance of queryable in the default graph.

  • :named_graph_uri (RDF::URI, String, Array<RDF::URI, String>)

    One or more URIs used to initialize the queryable as a named graph.

  • :update (Boolean) — default: false

    Parse starting with UpdateUnit production, QueryUnit otherwise.

  • :all_vars (Boolean) — default: false

    If true, emits on empty project operator when parsing SELECT *, which will emit all in-scope variables, rather than just those used in solutions. In the next minor release, the default for this option will change to true.

  • :anon_base (#to_s) — default: "b0"

    Basis for generating anonymous Nodes

  • :base_uri (#to_s) — default: nil

    the base URI to use when resolving relative URIs (for acessing intermediate parser productions)

  • :logger (Logger, #write, #<<)

    Record error/info/debug output

  • :prefixes (Hash) — default: Hash.new

    the prefix mappings to use (for acessing intermediate parser productions)

  • :resolve_iris (Boolean) — default: false

    Resolve prefix and relative IRIs, otherwise, when serializing the parsed SSE as S-Expressions, use the original prefixed and relative URIs along with base and prefix definitions.

  • :validate (Boolean) — default: false

    whether to validate the parsed statements and values

Yields:

  • (solution)

    each matching solution, statement or boolean

Yield Parameters:

Yield Returns:

  • (void)

    ignored

Returns:

Raises:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/sparql.rb', line 76

def self.execute(query, queryable, **options, &block)
  query = self.parse(query, **options)
  query = query.optimize(**options) if options[:optimize]
  queryable = queryable || RDF::Repository.new

  if options[:logger]
    options[:logger].debug("SPARQL.execute") {SXP::Generator.string query.to_sxp_bin}
  end

  if options.has_key?(:load_datasets)
    queryable = queryable.class.new
    [options[:default_graph_uri]].flatten.each do |uri|
      queryable.load(uri)
    end
    [options[:named_graph_uri]].flatten.each do |uri|
      queryable.load(uri, graph_name: uri)
    end
  end
  query.execute(queryable, **options, &block)
rescue SPARQL::Grammar::Parser::Error => e
  raise MalformedQuery, e.message
rescue TypeError => e
  raise QueryRequestRefused, e.message
end

.first_content_type(acceptable, available) ⇒ String

Find a content_type from a list using an ordered list of acceptable content types using wildcard matching

Parameters:

  • acceptable (Array<String>)
  • available (Array<String>)

Returns:

  • (String)

See Also:



313
314
315
316
317
318
319
320
321
# File 'lib/sparql/results.rb', line 313

def first_content_type(acceptable, available)
  return acceptable.first if available.empty?
  available.flatten!
  acceptable.each do |pattern|
    type = available.detect { |t| File.fnmatch(pattern, t) }
    return type if type
  end
  nil
end

.parse(query, **options) ⇒ RDF::Queryable

Parse the given SPARQL query string.

Examples:

query = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")

Parameters:

  • query (IO, StringIO, String, #to_s)
  • options (Hash{Symbol => Object})

Options Hash (**options):

  • :update (Boolean) — default: false

    Parse starting with UpdateUnit production, QueryUnit otherwise.

  • :all_vars (Boolean) — default: false

    If true, emits on empty project operator when parsing SELECT *, which will emit all in-scope variables, rather than just those used in solutions. In the next minor release, the default for this option will change to true.

  • :anon_base (#to_s) — default: "b0"

    Basis for generating anonymous Nodes

  • :base_uri (#to_s) — default: nil

    the base URI to use when resolving relative URIs (for acessing intermediate parser productions)

  • :logger (Logger, #write, #<<)

    Record error/info/debug output

  • :prefixes (Hash) — default: Hash.new

    the prefix mappings to use (for acessing intermediate parser productions)

  • :resolve_iris (Boolean) — default: false

    Resolve prefix and relative IRIs, otherwise, when serializing the parsed SSE as S-Expressions, use the original prefixed and relative URIs along with base and prefix definitions.

  • :validate (Boolean) — default: false

    whether to validate the parsed statements and values

Returns:

  • (RDF::Queryable)

    The resulting query may be executed against a queryable object such as an RDF::Graph or RDF::Repository.

Raises:

  • (SPARQL::Grammar::Parser::Error)

    on invalid input



35
36
37
# File 'lib/sparql.rb', line 35

def self.parse(query, **options)
  Grammar::Parser.new(query, **options).parse(options[:update] ? :UpdateUnit : :QueryUnit)
end

.serialize_exception(exception, **options) ⇒ String

Serialize error results

Returns appropriate content based upon an execution exception

Parameters:

  • exception (Exception)
  • options (Hash{Symbol => Object})

Options Hash (**options):

  • Format (:format)

    of results, one of :html, :json or :xml. May also be an RDF::Writer format to serialize DESCRIBE or CONSTRUCT results

  • Format (:content_type)

    of results, one of ‘application/sparql-results+json’ or ‘application/sparql-results+xml’ May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results

Returns:

  • (String)

    String with serialized results and #content_type



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/sparql/results.rb', line 338

def serialize_exception(exception, **options)
  format = options[:format]
  content_type = options[:content_type]
  content_type ||= SPARQL::Results::MIME_TYPES[format]
  serialization = case content_type
  when 'text/html'
    title = exception.respond_to?(:title) ? exception.title : exception.class.to_s
    ERROR_MESSAGE % [title, title, exception.message]
  else
    content_type = "text/plain"
    exception.message
  end
  
  serialization.instance_eval do
    define_singleton_method(:content_type) { content_type }
  end

  serialization
end

.serialize_results(solutions, **options) ⇒ String

Serialize solutions using the determined format

Parameters:

Options Hash (**options):

  • :format (#to_sym)

    Format of results, one of :html, :json or :xml. May also be an RDF::Writer format to serialize DESCRIBE or CONSTRUCT results

  • :content_type (String)

    Format of results, one of ‘application/sparql-results+json’ or ‘application/sparql-results+xml’ May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results

  • :content_types (Array<String>)

    Similar to :content_type, but takes an ordered array of appropriate content types, and serializes using the first appropriate type, including wild-cards.

Returns:

  • (String)

    String with serialized results and #content_type

Raises:

  • (RDF::WriterError)

    when inappropriate formatting options are used



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
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
# File 'lib/sparql/results.rb', line 215

def serialize_results(solutions, **options)
  format = options[:format].to_sym if options[:format]
  content_type = options[:content_type].to_s.split(';').first
  content_types = Array(options[:content_types] || '*/*')

  if !format && !content_type
    case solutions
    when RDF::Queryable
      content_type = first_content_type(content_types, RDF::Format.content_types.keys) || 'text/plain'
      format = RDF::Writer.for(content_type: content_type).to_sym
    else
      content_type = first_content_type(content_types, SPARQL::Results::MIME_TYPES.values) || 'application/sparql-results+xml'
      format = SPARQL::Results::MIME_TYPES.invert[content_type]
    end
  end

  serialization = case solutions
  when TrueClass, FalseClass, RDF::Literal::TRUE, RDF::Literal::FALSE
    solutions = solutions.object if solutions.is_a?(RDF::Literal)
    case format
    when :json
      require 'json' unless defined?(::JSON)
      {head: {}, boolean: solutions}.to_json
    when :xml
      require 'builder' unless defined?(::Builder)
      xml = ::Builder::XmlMarkup.new(indent: 2)
      xml.instruct!
      xml.sparql(xmlns: "http://www.w3.org/2005/sparql-results#") do
        xml.head
        xml.boolean(solutions.to_s)
      end
    when :html
      require 'builder' unless defined?(::Builder)
      content_type = "text/html"
      xml = ::Builder::XmlMarkup.new(indent: 2)
      xml.div(solutions.to_s, class: "sparql")
    else
      raise RDF::WriterError, "Unknown format #{(format || content_type).inspect} for #{solutions.class}"
    end
  when RDF::Queryable
    begin
      require 'linkeddata'
    rescue LoadError
      require 'rdf/ntriples'
    end
    fmt = RDF::Format.for(format ? format.to_sym : {content_type: content_type})
    unless fmt
      fmt = RDF::Format.for(file_extension: format.to_sym) || RDF::NTriples::Format
      format = fmt.to_sym
    end
    format ||= fmt.to_sym
    content_type ||= fmt.content_type.first
    results = solutions.dump(format, **options)
    raise RDF::WriterError, "Unknown format #{fmt.inspect} for #{solutions.class}" unless results
    results
  when RDF::Query::Solutions
    case format
    when :json  then solutions.to_json
    when :xml   then solutions.to_xml
    when :html  then solutions.to_html
    when :csv   then solutions.to_csv
    when :tsv   then solutions.to_tsv
    else
      raise RDF::WriterError, "Unknown format #{(format || content_type).inspect} for #{solutions.class}"
    end
  end

  content_type ||= SPARQL::Results::MIME_TYPES[format] if format

  serialization = serialization.dup if serialization.frozen?
  serialization.instance_eval do
    define_singleton_method(:content_type) { content_type }
  end
  
  serialization
end