From 3c71fdda9ef7283d5c80fd04bcc9a2b011828c67 Mon Sep 17 00:00:00 2001 From: Andy Seaborne Date: Wed, 18 Dec 2024 16:19:44 +0000 Subject: [PATCH] GH-2896: Inject values into (table unit) --- .../jena/sparql/algebra/table/Table1.java | 28 ++++++------ .../apache/jena/sparql/core/Substitute.java | 2 +- .../engine/iterator/QueryIterLateral.java | 43 +++++++++++++++++-- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/Table1.java b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/Table1.java index a7cc31ea1ae..1f21ad409b0 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/Table1.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/Table1.java @@ -24,7 +24,6 @@ import org.apache.jena.atlas.iterator.Iter ; import org.apache.jena.graph.Node ; -import org.apache.jena.riot.out.NodeFmtLib ; import org.apache.jena.sparql.core.Var ; import org.apache.jena.sparql.engine.ExecutionContext ; import org.apache.jena.sparql.engine.QueryIterator ; @@ -34,25 +33,24 @@ /** A table of one row of one binding */ public class Table1 extends TableBase { - private Var var ; - private Node value ; + private final Binding row; public Table1(Var var, Node value) { - this.var = var ; - this.value = value ; + this.row = BindingFactory.binding(var, value); + } + + public Table1(Binding row) { + this.row = row; } @Override public Iterator rows() { - Binding b = BindingFactory.binding(var, value) ; - return Iter.singletonIterator(b) ; + return Iter.singletonIterator(row) ; } @Override public QueryIterator iterator(ExecutionContext execCxt) { - // Root binding? - Binding binding = BindingFactory.binding(var, value) ; - QueryIterator qIter = QueryIterSingleton.create(null, var, value, execCxt) ; + QueryIterator qIter = QueryIterSingleton.create(row, execCxt) ; return qIter ; } @@ -61,15 +59,15 @@ public void closeTable() {} @Override public List getVars() { - List x = new ArrayList<>() ; - x.add(var) ; - return x ; + List x = new ArrayList<>(); + row.forEach((v,n)->x.add(v)); + return x; } @Override public List getVarNames() { List x = new ArrayList<>() ; - x.add(var.getVarName()) ; + row.forEach((v,n)->x.add(v.getName())); return x ; } @@ -85,6 +83,6 @@ public boolean isEmpty() { @Override public String toString() { - return "Table1(" + var + "," + NodeFmtLib.displayStr(value) + ")" ; + return "Table1(" + row + ")" ; } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/Substitute.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/Substitute.java index 19cbadc2963..5422913a2c4 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/Substitute.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/Substitute.java @@ -71,7 +71,7 @@ public class Substitute { */ public static Op inject(Op opInput, Binding binding) { Set injectVars = binding.varsMentioned(); - Transform transform = new QueryIterLateral.TransformInject(injectVars, binding::get); + Transform transform = new QueryIterLateral.TransformInject(injectVars, binding, binding::get); Op opOutput = Transformer.transform(transform, opInput); return opOutput; } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterLateral.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterLateral.java index 1162c6cb802..9ce2ce85a1f 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterLateral.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterLateral.java @@ -18,6 +18,7 @@ package org.apache.jena.sparql.engine.iterator; +import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -27,8 +28,11 @@ import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.sparql.algebra.Op; +import org.apache.jena.sparql.algebra.Table; import org.apache.jena.sparql.algebra.TransformCopy; import org.apache.jena.sparql.algebra.op.*; +import org.apache.jena.sparql.algebra.table.Table1; +import org.apache.jena.sparql.algebra.table.TableN; import org.apache.jena.sparql.core.*; import org.apache.jena.sparql.engine.ExecutionContext; import org.apache.jena.sparql.engine.QueryIterator; @@ -74,14 +78,14 @@ public static class TransformInject extends TransformCopy { private final Set injectVars; private final Set varsAsNodes; private final Function replacement; + private final Binding binding; private static final boolean substitute = true; - // Replacement becomes binding.?? - // Or "op call injection"!! - public TransformInject(Set injectVars, Function replacement) { + public TransformInject(Set injectVars, Binding binding) { this.injectVars = injectVars; this.varsAsNodes = Set.copyOf(injectVars); - this.replacement = replacement; + this.replacement = binding::get; + this.binding = binding; } @Override @@ -215,6 +219,7 @@ public Op transform(OpDatasetNames opDatasetNames) { // Basic Graph Pattern Matching // Property Path Patterns // evaluation of algebra form Graph(var,P) involving a variable (from the syntax GRAPH ?variable {…}) + // and also nested (table unit) inside (extend) @Override public Op transform(OpPath opPath) { @@ -270,6 +275,36 @@ public Op transform(OpTriple opTriple) { return opExec; } + private OpTable tableUnitTransformed = null; + + @Override + public Op transform(OpTable opTable) { + // Unit table. + if ( opTable.isJoinIdentity() ) { + if ( tableUnitTransformed == null ) { + Table table2 = new Table1(binding); + // Multiple assignment does not matter! + tableUnitTransformed = OpTable.create(table2); + } + return tableUnitTransformed; + } + + // By the assignment restriction, the binding only needs to be added to each row of the table. + Table table = opTable.getTable(); + // Table vars. + List vars = new ArrayList<>(table.getVars()); + binding.vars().forEachRemaining(vars::add); + TableN table2 = new TableN(vars); + BindingBuilder builder = BindingFactory.builder(); + table.iterator(null).forEachRemaining(row->{ + builder.reset(); + builder.addAll(row); + builder.addAll(binding); + table2.addBinding(builder.build()); + }); + return OpTable.create(table2); + } + private Triple applyReplacement(Triple triple, Function replacement) { Node s2 = applyReplacement(triple.getSubject(), replacement); Node p2 = applyReplacement(triple.getPredicate(), replacement);