class SPARQL::Client

A SPARQL 1.0/1.1 client for RDF.rb.

@see www.w3.org/TR/sparql11-query/ @see www.w3.org/TR/sparql11-protocol/ @see www.w3.org/TR/sparql11-results-json/ @see www.w3.org/TR/sparql11-results-csv-tsv/

Constants

ACCEPT_BRTR
ACCEPT_CSV
ACCEPT_GRAPH
ACCEPT_JSON
ACCEPT_RESULTS
ACCEPT_TSV
ACCEPT_XML
DEFAULT_METHOD
DEFAULT_PROTOCOL
GRAPH_ALL
RESULT_ALL
RESULT_BOOL
RESULT_BRTR
RESULT_CSV
RESULT_JSON
RESULT_TSV
RESULT_XML
XMLNS

Attributes

headers[R]

The HTTP headers that will be sent in requests to the endpoint.

@return [Hash{String => String}]

options[R]

Any miscellaneous configuration.

@return [Hash{Symbol => Object}]

url[R]

The SPARQL endpoint URL, or an RDF::Queryable instance, to use the native SPARQL engine.

@return [RDF::URI, RDF::Queryable]

Public Class Methods

finalize(klass) click to toggle source

Close the http connection when object is deallocated

# File lib/sparql/client.rb, line 117
def self.finalize(klass)
  proc do
    klass.shutdown if klass.respond_to?(:shutdown)
  end
end
new(url, **options, &block) click to toggle source

Initialize a new sparql client, either using the URL of a SPARQL endpoint or an `RDF::Queryable` instance to use the native SPARQL gem.

@param [String, RDF::Queryable, to_s] url

URL of endpoint, or queryable object.

@param [Hash{Symbol => Object}] options @option options [Symbol] :method (DEFAULT_METHOD) @option options [Number] :protocol (DEFAULT_PROTOCOL) @option options [Hash] :headers

HTTP Request headers

Defaults `Accept` header based on available reader content types if triples are expected and to SPARQL result types otherwise, to allow for content negotiation based on available readers.

Defaults  `User-Agent` header, unless one is specified.

@option options [Hash] :read_timeout

# File lib/sparql/client.rb, line 95
def initialize(url, **options, &block)
  case url
  when RDF::Queryable
    @url, @options = url, options.dup
  else
    @url, @options = RDF::URI.new(url.to_s), options.dup
    @headers = @options.delete(:headers) || {}
    @http = http_klass(@url.scheme)

    # Close the http connection when object is deallocated
    ObjectSpace.define_finalizer(self, self.class.finalize(@http))
  end

  if block_given?
    case block.arity
      when 1 then block.call(self)
      else instance_eval(&block)
    end
  end
end
parse_csv_bindings(csv, nodes = {}) click to toggle source

@param [String, Array<Array<String>>] csv @return [<RDF::Query::Solutions>] @see www.w3.org/TR/sparql11-results-csv-tsv/

# File lib/sparql/client.rb, line 453
def self.parse_csv_bindings(csv, nodes = {})
  require 'csv' unless defined?(::CSV)
  csv = CSV.parse(csv.to_s) unless csv.is_a?(Array)
  vars = csv.shift
  solutions = RDF::Query::Solutions.new
  csv.each do |row|
    solution = RDF::Query::Solution.new
    row.each_with_index do |v, i|
      term = case v
      when /^_:(.*)$/ then nodes[$1] ||= RDF::Node($1)
      when /^\w+:.*$/ then RDF::URI(v)
      else RDF::Literal(v)
      end
      solution[vars[i].to_sym] = term
    end
    solutions << solution
  end
  solutions
end
parse_json_bindings(json, nodes = {}) click to toggle source

@param [String, Hash] json @return [<RDF::Query::Solutions>] @see www.w3.org/TR/rdf-sparql-json-res/#results

# File lib/sparql/client.rb, line 413
def self.parse_json_bindings(json, nodes = {})
  require 'json' unless defined?(::JSON)
  json = JSON.parse(json.to_s) unless json.is_a?(Hash)
  case
    when json.has_key?('boolean')
      json['boolean']
    when json.has_key?('results')
      solutions = json['results']['bindings'].map do |row|
        row = row.inject({}) do |cols, (name, value)|
          cols.merge(name.to_sym => parse_json_value(value, nodes))
        end
        RDF::Query::Solution.new(row)
      end
      RDF::Query::Solutions.new(solutions)
  end
end
parse_json_value(value, nodes = {}) click to toggle source

@param [Hash{String => String}] value @return [RDF::Value] @see www.w3.org/TR/sparql11-results-json/#select-encode-terms @see www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results

# File lib/sparql/client.rb, line 435
def self.parse_json_value(value, nodes = {})
  case value['type'].to_sym
    when :bnode
      nodes[id = value['value']] ||= RDF::Node.new(id)
    when :uri
      RDF::URI.new(value['value'])
    when :literal
      RDF::Literal.new(value['value'], datatype: value['datatype'], language: value['xml:lang'])
    when :'typed-literal'
      RDF::Literal.new(value['value'], datatype: value['datatype'])
    else nil
  end
end
parse_tsv_bindings(tsv, nodes = {}) click to toggle source

@param [String, Array<Array<String>>] tsv @return [<RDF::Query::Solutions>] @see www.w3.org/TR/sparql11-results-csv-tsv/

# File lib/sparql/client.rb, line 477
def self.parse_tsv_bindings(tsv, nodes = {})
  tsv = tsv.lines.map {|l| l.chomp.split("\t")} unless tsv.is_a?(Array)
  vars = tsv.shift.map {|h| h.sub(/^\?/, '')}
  solutions = RDF::Query::Solutions.new
  tsv.each do |row|
    solution = RDF::Query::Solution.new
    row.each_with_index do |v, i|
      if !v.empty?
        term = RDF::NTriples.unserialize(v) || case v
        when /^\d+\.\d*[eE][+-]?[0-9]+$/  then RDF::Literal::Double.new(v)
        when /^\d*\.\d+[eE][+-]?[0-9]+$/  then RDF::Literal::Double.new(v)
        when /^\d*\.\d+$/                 then RDF::Literal::Decimal.new(v)
        when /^\d+$/                      then RDF::Literal::Integer.new(v)
        else
          RDF::Literal(v)
        end
        nodes[term.id] = term if term.is_a? RDF::Node
        solution[vars[i].to_sym] = term
      end
    end
    solutions << solution
  end
  solutions
end
parse_xml_bindings(xml, nodes = {}) click to toggle source

@param [String, IO, Nokogiri::XML::Node, REXML::Element] xml @return [<RDF::Query::Solutions>] @see www.w3.org/TR/rdf-sparql-json-res/#results

# File lib/sparql/client.rb, line 506
def self.parse_xml_bindings(xml, nodes = {})
  xml.force_encoding(::Encoding::UTF_8) if xml.respond_to?(:force_encoding)

  if defined?(::Nokogiri)
    xml = Nokogiri::XML(xml).root unless xml.is_a?(Nokogiri::XML::Document)
    case
      when boolean = xml.xpath("//sparql:boolean", XMLNS)[0]
        boolean.text == 'true'
      when results = xml.xpath("//sparql:results", XMLNS)[0]
        solutions = results.elements.map do |result|
          row = {}
          result.elements.each do |binding|
            name  = binding.attr('name').to_sym
            value = binding.elements.first
            row[name] = parse_xml_value(value, nodes)
          end
          RDF::Query::Solution.new(row)
        end
        RDF::Query::Solutions.new(solutions)
    end
  else
    # REXML
    xml = REXML::Document.new(xml).root unless xml.is_a?(REXML::Element)
    case
      when boolean = xml.elements['boolean']
        boolean.text == 'true'
      when results = xml.elements['results']
        solutions = results.elements.map do |result|
          row = {}
          result.elements.each do |binding|
            name  = binding.attributes['name'].to_sym
            value = binding.select { |node| node.kind_of?(::REXML::Element) }.first
            row[name] = parse_xml_value(value, nodes)
          end
          RDF::Query::Solution.new(row)
        end
        RDF::Query::Solutions.new(solutions)
    end
  end
end
parse_xml_value(value, nodes = {}) click to toggle source

@param [Nokogiri::XML::Element, REXML::Element] value @return [RDF::Value] @see www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results

# File lib/sparql/client.rb, line 551
def self.parse_xml_value(value, nodes = {})
  case value.name.to_sym
    when :bnode
      nodes[id = value.text] ||= RDF::Node.new(id)
    when :uri
      RDF::URI.new(value.text)
    when :literal
      lang     = value.respond_to?(:attr) ? value.attr('xml:lang') : value.attributes['xml:lang']
      datatype = value.respond_to?(:attr) ? value.attr('datatype') : value.attributes['datatype']
      RDF::Literal.new(value.text, language: lang, datatype: datatype)
    else nil
  end
end
serialize_patterns(patterns, use_vars = false) click to toggle source

Serializes a SPARQL graph

@param [RDF::Enumerable] patterns @param [Boolean] use_vars (false) Use variables in place of BNodes @return [String] @private

# File lib/sparql/client.rb, line 638
def self.serialize_patterns(patterns, use_vars = false)
  patterns.map do |pattern|
    serialized_pattern = case pattern
    when SPARQL::Client::QueryElement then [pattern.to_s]
    else
      RDF::Statement.from(pattern).to_triple.each_with_index.map do |v, i|
        if i == 1
          SPARQL::Client.serialize_predicate(v)
        else
          SPARQL::Client.serialize_value(v, use_vars)
        end
      end
    end
    serialized_pattern.join(' ') + ' .'
  end
end
serialize_predicate(value,rdepth=0) click to toggle source

Serializes a SPARQL predicate

@param [RDF::Value, Array, String] value @param [Fixnum] rdepth @return [String] @private

# File lib/sparql/client.rb, line 617
def self.serialize_predicate(value,rdepth=0)
  case value
    when nil
      RDF::Query::Variable.new.to_s
    when String then value
    when Array
      s = value.map{|v|serialize_predicate(v,rdepth+1)}.join
      rdepth > 0 ? "(#{s})" : s
    when RDF::Value
      # abbreviate RDF.type in the predicate position per SPARQL grammar
      value.equal?(RDF.type) ? 'a' : serialize_value(value)
  end
end
serialize_uri(uri) click to toggle source

Serializes a URI or URI string into SPARQL syntax.

@param [RDF::URI, String] uri @return [String] @private

# File lib/sparql/client.rb, line 584
def self.serialize_uri(uri)
  case uri
    when String then RDF::NTriples.serialize(RDF::URI(uri))
    when RDF::URI then RDF::NTriples.serialize(uri)
    else raise ArgumentError, "expected the graph URI to be a String or RDF::URI, but got #{uri.inspect}"
  end
end
serialize_value(value, use_vars = false) click to toggle source

Serializes an `RDF::Value` into SPARQL syntax.

@param [RDF::Value] value @param [Boolean] use_vars (false) Use variables in place of BNodes @return [String] @private

# File lib/sparql/client.rb, line 599
def self.serialize_value(value, use_vars = false)
  # 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.nil?      then RDF::Query::Variable.new.to_s
    when value.variable? then value.to_s
    when value.node?     then (use_vars ? RDF::Query::Variable.new(value.id) : value)
    else RDF::NTriples.serialize(value)
  end
end

Public Instance Methods

ask(*args, **options) click to toggle source

Executes a boolean `ASK` query.

@param (see Query.ask) @return [Query]

# File lib/sparql/client.rb, line 138
def ask(*args, **options)
  call_query_method(:ask, *args, **options)
end
call_query_method(meth, *args, **options) click to toggle source

@private

# File lib/sparql/client.rb, line 291
def call_query_method(meth, *args, **options)
  client = self
  result = Query.send(meth, *args, **options)
  (class << result; self; end).send(:define_method, :execute) do
    client.query(self)
  end
  result
end
clear(what, *arguments) click to toggle source

Executes a `CLEAR` operation.

This requires that the endpoint support SPARQL 1.1 Update.

@example `CLEAR GRAPH <example.org/>`

client.clear(:graph, RDF::URI("http://example.org/"))

@example `CLEAR DEFAULT`

client.clear(:default)

@example `CLEAR NAMED`

client.clear(:named)

@example `CLEAR ALL`

client.clear(:all)

@overload clear(what, *arguments)

@param  [Symbol, #to_sym] what
@param  [Array] arguments splat of other arguments to {Update::Clear}.
@option options [Boolean] :silent
@return [void] `self`

@overload clear(what, *arguments, **options)

@param  [Symbol, #to_sym] what
@param  [Array] arguments splat of other arguments to {Update::Clear}.
@param  [Hash{Symbol => Object}] options
@option options [Boolean] :silent
@return [void] `self`

@see www.w3.org/TR/sparql11-update/#clear

# File lib/sparql/client.rb, line 285
def clear(what, *arguments)
  self.update(Update::Clear.new(what, *arguments))
end
clear_graph(graph_uri, **options) click to toggle source

Executes a `CLEAR GRAPH` operation.

This is a convenience wrapper for the {#clear} method.

@example `CLEAR GRAPH <example.org/>`

client.clear_graph("http://example.org/")

@param [RDF::URI, String] graph_uri @param [Hash{Symbol => Object}] options @option options [Boolean] :silent @return [void] `self` @see www.w3.org/TR/sparql11-update/#clear

# File lib/sparql/client.rb, line 250
def clear_graph(graph_uri, **options)
  self.clear(:graph, graph_uri, **options)
end
close() click to toggle source

Closes a client instance by finishing the connection. The client is unavailable for any further data operations; an IOError is raised if such an attempt is made. I/O streams are automatically closed when they are claimed by the garbage collector. @return [void] `self`

# File lib/sparql/client.rb, line 127
def close
  @http.shutdown if @http
  @http = nil
  self
end
construct(*args, **options) click to toggle source

Executes a graph `CONSTRUCT` query.

@param (see Query.construct) @return [Query]

# File lib/sparql/client.rb, line 165
def construct(*args, **options)
  call_query_method(:construct, *args, **options)
end
delete_data(data, **options) click to toggle source

Executes a `DELETE DATA` operation.

This requires that the endpoint support SPARQL 1.1 Update.

@example Deleting data sourced from a file or URL

data = RDF::Graph.load("https://raw.githubusercontent.com/ruby-rdf/rdf/develop/etc/doap.nt")
client.delete_data(data)

@example Deleting data from a named graph

client.delete_data(data, graph: "http://example.org/")

@param [RDF::Enumerable] data @param [Hash{Symbol => Object}] options @option options [RDF::URI, String] :graph @return [void] `self` @see www.w3.org/TR/sparql11-update/#deleteData

# File lib/sparql/client.rb, line 217
def delete_data(data, **options)
  self.update(Update::DeleteData.new(data, **options))
end
delete_insert(delete_graph, insert_graph = nil, where_graph = nil, **options) click to toggle source

Executes a `DELETE/INSERT` operation.

This requires that the endpoint support SPARQL 1.1 Update.

@param [RDF::Enumerable] delete_graph @param [RDF::Enumerable] insert_graph @param [RDF::Enumerable] where_graph @param [Hash{Symbol => Object}] options @option options [RDF::URI, String] :graph @return [void] `self` @see www.w3.org/TR/sparql11-update/#deleteInsert

# File lib/sparql/client.rb, line 233
def delete_insert(delete_graph, insert_graph = nil, where_graph = nil, **options)
  self.update(Update::DeleteInsert.new(delete_graph, insert_graph, where_graph, **options))
end
describe(*args, **options) click to toggle source

Executes a `DESCRIBE` query.

@param (see Query.describe) @return [Query]

# File lib/sparql/client.rb, line 156
def describe(*args, **options)
  call_query_method(:describe, *args, **options)
end
insert_data(data, **options) click to toggle source

Executes an `INSERT DATA` operation.

This requires that the endpoint support SPARQL 1.1 Update.

Note that for inserting non-trivial amounts of data, you probably ought to consider using the RDF store's native bulk-loading facilities or APIs, as `INSERT DATA` operations entail comparably higher parsing overhead.

@example Inserting data constructed ad-hoc

client.insert_data(RDF::Graph.new { |graph|
  graph << [:jhacker, RDF::Vocab::FOAF.name, "J. Random Hacker"]
})

@example Inserting data sourced from a file or URL

data = RDF::Graph.load("https://raw.githubusercontent.com/ruby-rdf/rdf/develop/etc/doap.nt")
client.insert_data(data)

@example Inserting data into a named graph

client.insert_data(data, graph: "http://example.org/")

@param [RDF::Enumerable] data @param [Hash{Symbol => Object}] options @option options [RDF::URI, String] :graph @return [void] `self` @see www.w3.org/TR/sparql11-update/#insertData

# File lib/sparql/client.rb, line 196
def insert_data(data, **options)
  self.update(Update::InsertData.new(data, **options))
end
inspect() click to toggle source

Returns a developer-friendly representation of this object.

@return [String]

# File lib/sparql/client.rb, line 667
def inspect
  sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, url.to_s)
end
inspect!() click to toggle source

Outputs a developer-friendly representation of this object to `stderr`.

@return [void]

# File lib/sparql/client.rb, line 659
def inspect!
  warn(inspect)
end
nodes() click to toggle source

Returns a mapping of blank node results for this client.

@private

# File lib/sparql/client.rb, line 304
def nodes
  @nodes ||= {}
end
parse_rdf_serialization(response, **options) click to toggle source

@param [Net::HTTPSuccess] response @param [Hash{Symbol => Object}] options @return [RDF::Enumerable]

# File lib/sparql/client.rb, line 569
def parse_rdf_serialization(response, **options)
  options = {content_type: response.content_type} unless options[:content_type]
  if reader = RDF::Reader.for(options)
    reader.new(response.body)
  else
    raise RDF::ReaderError, "no RDF reader was found for #{options}."
  end
end
parse_response(response, **options) click to toggle source

@param [Net::HTTPSuccess] response @param [Hash{Symbol => Object}] options @return [Object]

# File lib/sparql/client.rb, line 390
def parse_response(response, **options)
  case options[:content_type] || response.content_type
    when NilClass
      response.body
    when RESULT_BOOL # Sesame-specific
      response.body == 'true'
    when RESULT_JSON
      self.class.parse_json_bindings(response.body, nodes)
    when RESULT_XML
      self.class.parse_xml_bindings(response.body, nodes)
    when RESULT_CSV
      self.class.parse_csv_bindings(response.body, nodes)
    when RESULT_TSV
      self.class.parse_tsv_bindings(response.body, nodes)
    else
      parse_rdf_serialization(response, **options)
  end
end
query(query, **options) click to toggle source

Executes a SPARQL query and returns the parsed results.

@param [String, to_s] query @param [Hash{Symbol => Object}] options @option options [String] :content_type @option options [Hash] :headers @return [Array<RDF::Query::Solution>] @raise [IOError] if connection is closed @see www.w3.org/TR/sparql11-protocol/#query-operation

# File lib/sparql/client.rb, line 318
def query(query, **options)
  @op = :query
  @alt_endpoint = options[:endpoint]
  case @url
  when RDF::Queryable
    require 'sparql' unless defined?(::SPARQL::Grammar)
    begin
      SPARQL.execute(query, @url, optimize: true, **options)
    rescue SPARQL::MalformedQuery
      $stderr.puts "error running #{query}: #{$!}"
      raise
    end
  else
    parse_response(response(query, **options), **options)
  end
end
response(query, **options) click to toggle source

Executes a SPARQL query and returns the Net::HTTP::Response of the result.

@param [String, to_s] query @param [Hash{Symbol => Object}] options @option options [String] :content_type @option options [Hash] :headers @return [String] @raise [IOError] if connection is closed

# File lib/sparql/client.rb, line 369
def response(query, **options)
  headers = options[:headers] || @headers
  headers['Accept'] = options[:content_type] if options[:content_type]
  request(query, headers) do |response|
    case response
      when Net::HTTPBadRequest  # 400 Bad Request
        raise MalformedQuery.new(response.body + " Processing query #{query}")
      when Net::HTTPClientError # 4xx
        raise ClientError.new(response.body + " Processing query #{query}")
      when Net::HTTPServerError # 5xx
        raise ServerError.new(response.body + " Processing query #{query}")
      when Net::HTTPSuccess     # 2xx
        response
    end
  end
end
select(*args, **options) click to toggle source

Executes a tuple `SELECT` query.

@param (see Query.select) @return [Query]

# File lib/sparql/client.rb, line 147
def select(*args, **options)
  call_query_method(:select, *args, **options)
end
update(query, **options) click to toggle source

Executes a SPARQL update operation.

@param [String, to_s] query @param [Hash{Symbol => Object}] options @option options [String] :endpoint @option options [String] :content_type @option options [Hash] :headers @return [void] `self` @raise [IOError] if connection is closed @see www.w3.org/TR/sparql11-protocol/#update-operation

# File lib/sparql/client.rb, line 346
def update(query, **options)
  @op = :update
  @alt_endpoint = options[:endpoint]
  case @url
  when RDF::Queryable
    require 'sparql' unless defined?(::SPARQL::Grammar)
    SPARQL.execute(query, @url, update: true, optimize: true, **options)
  else
    response(query, **options)
  end
  self
end

Protected Instance Methods

http_klass(scheme) click to toggle source

Returns an HTTP class or HTTP proxy class based on the `http_proxy` and `https_proxy` environment variables.

@param [String] scheme @return [Net::HTTP::Proxy]

# File lib/sparql/client.rb, line 679
def http_klass(scheme)
  proxy_url = nil
  case scheme
    when 'http'
      value = ENV['http_proxy']
      proxy_url = URI.parse(value) unless value.nil? || value.empty?
    when 'https'
      value = ENV['https_proxy']
      proxy_url = URI.parse(value) unless value.nil? || value.empty?
  end
  klass = Net::HTTP::Persistent.new(name: self.class.to_s, proxy: proxy_url)
  klass.keep_alive =  @options[:keep_alive] || 120
  klass.read_timeout = @options[:read_timeout] || 60
  klass
end
make_get_request(query, headers = {}) click to toggle source

Constructs an HTTP GET request according to the SPARQL Protocol.

@param [String, to_s] query @param [Hash{String => String}] headers @return [Net::HTTPRequest] @see www.w3.org/TR/sparql11-protocol/#query-via-get

# File lib/sparql/client.rb, line 758
def make_get_request(query, headers = {})
  url = self.url.dup
  url.query_values = (url.query_values || {}).merge(query: query.to_s)
  set_url_default_graph url unless @options[:graph].nil?
  request = Net::HTTP::Get.new(url.request_uri, self.headers.merge(headers))
  request
end
make_post_request(query, headers = {}) click to toggle source

Constructs an HTTP POST request according to the SPARQL Protocol.

@param [String, to_s] query @param [Hash{String => String}] headers @return [Net::HTTPRequest] @see www.w3.org/TR/sparql11-protocol/#query-via-post-direct @see www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded

# File lib/sparql/client.rb, line 774
def make_post_request(query, headers = {})
  if @alt_endpoint.nil?
    url = self.url.dup
    set_url_default_graph url unless @options[:graph].nil?
    endpoint = url.request_uri
  else
    endpoint = @alt_endpoint
  end

  request = Net::HTTP::Post.new(endpoint, self.headers.merge(headers))
  case (self.options[:protocol] || DEFAULT_PROTOCOL).to_s
    when '1.1'
      request['Content-Type'] = 'application/sparql-' + (@op || :query).to_s
      request.body = query.to_s
    when '1.0'
      form_data = {(@op || :query) => query.to_s}
      form_data.merge!(
        {:'default-graph-uri' => @options[:graph]}
      ) if !@options[:graph].nil? && (@op.eql? :query)
      form_data.merge!(
        {:'using-graph-uri' => @options[:graph]}
      ) if !@options[:graph].nil? && (@op.eql? :update)
      request.set_form_data(form_data)
    else
      raise ArgumentError, "unknown SPARQL protocol version: #{self.options[:protocol].inspect}"
  end
  request
end
request(query, headers = {}, &block) click to toggle source

Performs an HTTP request against the SPARQL endpoint.

@param [String, to_s] query @param [Hash{String => String}] headers

HTTP Request headers

Defaults `Accept` header based on available reader content types if triples are expected and to SPARQL result types otherwise, to allow for content negotiation based on available readers.

Defaults  `User-Agent` header, unless one is specified.

@yield [response] @yieldparam [Net::HTTPResponse] response @return [Net::HTTPResponse] @raise [IOError] if connection is closed @see www.w3.org/TR/sparql11-protocol/#query-operation

# File lib/sparql/client.rb, line 710
def request(query, headers = {}, &block)
  # Make sure an appropriate Accept header is present
  headers['Accept'] ||= if (query.respond_to?(:expects_statements?) ?
                            query.expects_statements? :
                            (query =~ /CONSTRUCT|DESCRIBE|DELETE|CLEAR/))
    GRAPH_ALL
  else
    RESULT_ALL
  end
  headers['User-Agent'] ||= "Ruby SPARQL::Client/#{SPARQL::Client::VERSION}"

  request = send("make_#{request_method(query)}_request", query, headers)

  request.basic_auth(url.user, url.password) if url.user && !url.user.empty?

  pre_http_hook(request) if respond_to?(:pre_http_hook)

  raise IOError, "Client has been closed" unless @http
  response = @http.request(::URI.parse(url.to_s), request)

  post_http_hook(response) if respond_to?(:post_http_hook)

  10.times do
    if response.kind_of? Net::HTTPRedirection
      response = @http.request(::URI.parse(response['location']), request)
    else
      return block_given? ? block.call(response) : response
    end
  end
  raise ServerError, "Infinite redirect at #{url}. Redirected more than 10 times."
end
request_method(query) click to toggle source

Return the HTTP verb for posting this request. this is useful if you need to override the HTTP verb based on the request being made. (e.g. Marmotta 3.3.0 requires GET for DELETE requests, but can accept POST for INSERT)

# File lib/sparql/client.rb, line 746
def request_method(query)
  (options[:method] || DEFAULT_METHOD).to_sym
end
set_url_default_graph(url) click to toggle source

Setup url query parameter to use a specified default graph

@see www.w3.org/TR/sparql11-protocol/#query-operation @see www.w3.org/TR/sparql11-protocol/#update-operation

# File lib/sparql/client.rb, line 808
def set_url_default_graph url
  if @options[:graph].is_a? Array
    graphs = @options[:graph].map {|graph|
      CGI::escape(graph)
    }
  else
    graphs = CGI::escape(@options[:graph])
  end
  case @op
  when :query
    url.query_values = (url.query_values || {})
      .merge(:'default-graph-uri' => graphs)
  when :update
    url.query_values = (url.query_values || {})
      .merge(:'using-graph-uri' => graphs)
  end
end