module SPARQL; module Algebra class Operator ## # The SPARQL `coalesce` function. # # [121] BuiltInCall ::= ... | 'COALESCE' ExpressionList # # @example SPARQL Grammar # PREFIX : <http://example/> # PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> # # SELECT ?X (SAMPLE(?v) AS ?S) # { # ?s :p ?v . # OPTIONAL { ?s :q ?w } # } # GROUP BY (COALESCE(?w, "1605-11-05"^^xsd:date) AS ?X) # # @example SSE # (prefix # ((: <http://example/>) (xsd: <http://www.w3.org/2001/XMLSchema#>)) # (project (?X ?S) # (extend ((?S ??.0)) # (group # ((?X (coalesce ?w "1605-11-05"^^xsd:date))) # ((??.0 (sample ?v))) # (leftjoin # (bgp (triple ?s :p ?v)) # (bgp (triple ?s :q ?w))))))) # # @see https://www.w3.org/TR/sparql11-query/#func-coalesce class Coalesce < Operator include Evaluatable NAME = :coalesce ## # The COALESCE function form returns the RDF term value of the first expression that evaluates without error. In SPARQL, evaluating an unbound variable raises an error. # # If none of the arguments evaluates to an RDF term, an error is raised. If no expressions are evaluated without error, an error is raised. # # @example # Suppose ?x = 2 and ?y is not bound in some query solution: # # COALESCE(?x, 1/0) #=> 2, the value of x # COALESCE(1/0, ?x) #=> 2 # COALESCE(5, ?x) #=> 5 # COALESCE(?y, 3) #=> 3 # COALESCE(?y) #=> raises an error because y is not bound. # # @param [RDF::Query::Solution] bindings # a query solution containing zero or more variable bindings # @param [Hash{Symbol => Object}] options ({}) # options passed from query # @return [RDF::Term] # @raise [TypeError] if none of the operands succeeds def evaluate(bindings, **options) operands.each do |op| begin return op.evaluate(bindings, depth: options[:depth].to_i + 1, **options) rescue end end raise TypeError, "None of the operands evaluated" end ## # # Returns a partial SPARQL grammar for this operator. # # @return [String] def to_sparql(**options) "COALESCE(#{operands.to_sparql(delimiter: ', ', **options)})" end end # Coalesce end # Operator end; end # SPARQL::Algebra