Skip to content

Commit

Permalink
apacheGH-2218: Implement LATERAL as per SEP-0006/SEP-0007
Browse files Browse the repository at this point in the history
  • Loading branch information
afs committed Feb 1, 2024
1 parent bdb4df2 commit 17d97ae
Show file tree
Hide file tree
Showing 9 changed files with 437 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.graph.Triple;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.algebra.Transform;
import org.apache.jena.sparql.algebra.TransformCopy;
import org.apache.jena.sparql.algebra.Transformer;
import org.apache.jena.sparql.algebra.op.*;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.engine.binding.BindingFactory;
import org.apache.jena.sparql.engine.iterator.QueryIterLateral;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.pfunction.PropFuncArg;
Expand All @@ -40,12 +43,42 @@
* Substitution in SPARQL algebra.
* <p>
* See also {@link QueryTransformOps} and {@link UpdateTransformOps} which operate on SPARQL syntax.
* <p>
* {@link #inject} provides the substitution, while leaving a variable present, used by LATERAL.
*/
public class Substitute {
/**
* Inject takes an {@link Op} to transform using a {Binding binding}. The
* transformation assumes the Ope structure is legal for the operation. The
* transformation is to wrap each place a variable is used (BGP, GRAPH, Path and
* some equivalent operations) with a {@code BIND} to restrict the vartibale to a specific value
* while still retaining the variable (e.g for FILETERs).
* <p>
* <pre>
* (bgp
* (?s :p 123)
* (?s :q ?a)
* )
* </pre>
* with binding {@code ?s = :x } becomes
* <pre>
* (assign (?s :x)
* (bgp
* (:x :p 123)
* (:x :q ?a)
* ))
* </pre>
*/
public static Op inject(Op opInput, Binding binding) {
Set<Var> injectVars = binding.varsMentioned();
Transform transform = new QueryIterLateral.TransformInject(injectVars, binding::get);
Op opOutput = Transformer.transform(transform, opInput);
return opOutput;
}

public static Op substitute(Op op, Binding binding) {
// Want to avoid cost if the binding is empty
// but the empty test is not zero-cost on non-empty things.

if ( isNotNeeded(binding) )
return op;
return Transformer.transform(new OpSubstituteWorker(binding), op);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public class VarExprList {
private List<Var> vars;
private LinkedHashMap<Var, Expr> exprs; // Preserve order.

public VarExprList(List<Var> vars) {
this.vars = new ArrayList<>(vars);
this.exprs = new LinkedHashMap<>();
}
// public VarExprList(List<Var> vars) {
// this.vars = new ArrayList<>(vars);
// this.exprs = new LinkedHashMap<>();
// }

public VarExprList(VarExprList other) {
this.vars = new ArrayList<>(other.vars);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.apache.jena.sparql.engine.binding;

import java.util.Iterator;
import java.util.Set;
import java.util.function.BiConsumer;

import org.apache.jena.graph.Node;
Expand Down Expand Up @@ -56,6 +57,9 @@ public static BindingBuilder builder(Binding parent) {
/** Iterate over all variables of this binding. */
public Iterator<Var> vars();

/** Iterate over all variables of this binding. */
public Set<Var> varsMentioned();

/** Operate on each entry. */
public void forEach(BiConsumer<Var, Node> action);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
package org.apache.jena.sparql.engine.binding;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.BiConsumer;

import org.apache.jena.atlas.iterator.IteratorConcat;
Expand All @@ -45,14 +47,20 @@ protected BindingBase(Binding _parent) {
// public Binding getParent() { return parent; }

@Override
final public Iterator<Var> vars()
{
final public Iterator<Var> vars() {
Iterator<Var> iter = vars1();
if ( parent != null )
iter = IteratorConcat.concat(parent.vars(), iter);
return iter;
}

@Override
final public Set<Var> varsMentioned() {
Set<Var> result = new LinkedHashSet<>();
vars().forEachRemaining(result::add);
return result;
}

/** Operate on each entry. */
@Override
public void forEach(BiConsumer<Var, Node> action) {
Expand Down
Loading

0 comments on commit 17d97ae

Please sign in to comment.