Class: LD::Patch::Algebra::UpdateList

Inherits:
SPARQL::Algebra::Operator show all
Includes:
SPARQL::Algebra::Evaluatable, SPARQL::Algebra::Update
Defined in:
vendor/bundler/ruby/3.3.0/bundler/gems/ld-patch-a8edc852261e/lib/ld/patch/algebra/update_list.rb

Overview

The LD Patch updateList operator.

The UpdateList operation is used to splice a new list into a subset of an existing list.

Constant Summary collapse

NAME =
:updateList

Constants inherited from SPARQL::Algebra::Operator

SPARQL::Algebra::Operator::ARITY, SPARQL::Algebra::Operator::IsURI, SPARQL::Algebra::Operator::URI

Constants included from SPARQL::Algebra::Expression

SPARQL::Algebra::Expression::PATTERN_PARENTS

Constants included from RDF::Util::Logger

RDF::Util::Logger::IOWrapper

Instance Attribute Summary

Attributes inherited from SPARQL::Algebra::Operator

#operands

Instance Method Summary collapse

Methods included from SPARQL::Algebra::Evaluatable

#apply, #evaluate, #memoize, #replace_aggregate!, #replace_vars!

Methods included from SPARQL::Algebra::Update

#graph_name=, #unshift, #variables

Methods inherited from SPARQL::Algebra::Operator

#aggregate?, arity, base_uri, #base_uri, base_uri=, #bind, #boolean, #constant?, #deep_dup, #each_descendant, #eql?, #evaluatable?, evaluate, #executable?, #first_ancestor, for, #formulae, #initialize, #inspect, #ndvars, #node?, #operand, #optimize, #optimize!, #parent, #parent=, prefixes, #prefixes, prefixes=, #rewrite, #to_binary, #to_sparql, to_sparql, #to_sxp, #to_sxp_bin, #validate!, #variable?, #variables, #vars

Methods included from SPARQL::Algebra::Expression

cast, #constant?, #evaluate, extension, extension?, extensions, for, #invalid?, new, #node?, open, #optimize, #optimize!, parse, register_extension, #to_sxp_bin, #valid?, #validate!, #variable?

Methods included from RDF::Util::Logger

#log_debug, #log_depth, #log_error, #log_fatal, #log_info, #log_recover, #log_recovering?, #log_statistics, #log_warn, #logger

Constructor Details

This class inherits a constructor from SPARQL::Algebra::Operator

Instance Method Details

#execute(queryable, options = {}) ⇒ RDF::Query::Solutions

Executes this upate on the given writable graph or repository.

Parameters:

Returns:

  • (RDF::Query::Solutions)

    A single solution including passed bindings with var bound to the solution.

Raises:

  • (Error)

    If the subject and predicate provided to an UpdateList do not have a unique object, or if this object is not a well-formed collection. If an index in a slice expression is greater than the length of the rdf:List or otherwise out of bound.

See Also:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'vendor/bundler/ruby/3.3.0/bundler/gems/ld-patch-a8edc852261e/lib/ld/patch/algebra/update_list.rb', line 26

def execute(queryable, options = {})
  debug(options) {"UpdateList"}
  bindings = options.fetch(:bindings)
  solution = bindings.first
  var_or_iri, predicate, slice1, slice2, collection = operands

  # Bind variables to path
  if var_or_iri.variable?
    raise LD::Patch::Error("Operand uses unbound variable #{var_or_iri.inspect}", code: 400) unless solution.bound?(var_or_iri)
    var_or_iri = solution[var_or_iri]
  end

  list_heads = queryable.query({subject: var_or_iri, predicate: predicate}).map {|s| s.object}

  raise LD::Patch::Error, "UpdateList ambigious value for #{var_or_iri.to_ntriples} and #{predicate.to_ntriples}" if list_heads.length > 1
  raise LD::Patch::Error, "UpdateList no value found for #{var_or_iri.to_ntriples} and #{predicate.to_ntriples}" if list_heads.empty?
  lh = list_heads.first
  list = RDF::List.new(subject: lh, graph: queryable)
  raise LD::Patch::Error, "Invalid list" unless list.valid?

  start = case
  when slice1.nil? || slice1 == RDF.nil then list.length
  when slice1 < 0 then list.length + slice1.to_i
  else slice1.to_i
  end

  finish = case
  when slice2.nil? || slice2 == RDF.nil then list.length
  when slice2 < 0 then list.length + slice2.to_i
  else slice2.to_i
  end

  raise LD::Patch::Error.new("UpdateList slice indexes out of order #{start}..#{finish}}", code: 400) if finish < start
  
  length = finish - start
  raise LD::Patch::Error, "UpdateList out of bounds #{start}..#{finish}}" if start + length > list.length
  raise LD::Patch::Error, "UpdateList out of bounds #{start}..#{finish}}" if start < 0

  # Uses #[]= logic in RDF::List
  list[start, length] = collection
  new_lh = list.subject

  # If lh was rdf:nil, then we may have a new list head. Similarly, if the list was emptied, we now need to replace the head
  if lh != new_lh
    queryable.delete(RDF::Statement(var_or_iri, predicate, lh))
    queryable.insert(RDF::Statement(var_or_iri, predicate, new_lh))
  end

  bindings
end