This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new b7352cb5bd GH-2896: Inject values into (table unit)
b7352cb5bd is described below

commit b7352cb5bd71e7076eb7cf62fce2b6b333297ce6
Author: Andy Seaborne <[email protected]>
AuthorDate: Wed Dec 18 16:19:44 2024 +0000

    GH-2896: Inject values into (table unit)
---
 .../apache/jena/sparql/algebra/table/Table1.java   | 28 ++++++------
 .../org/apache/jena/sparql/core/Substitute.java    |  4 +-
 .../sparql/engine/iterator/QueryIterLateral.java   | 43 +++++++++++++++++--
 .../org/apache/jena/sparql/exec/TS_ExecSPARQL.java |  3 +-
 .../jena/sparql/exec/TestQueryExecution.java       | 50 ++++++++++++++++++++++
 jena-cmds/src/main/java/arq/cmdline/ModEngine.java | 27 ++++++------
 jena-cmds/src/main/java/arq/query.java             | 37 ++++++++--------
 7 files changed, 138 insertions(+), 54 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 a7cc31ea1a..1f21ad409b 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 java.util.List ;
 
 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 @@ import 
org.apache.jena.sparql.engine.iterator.QueryIterSingleton ;
 
 /** 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<Binding> 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 class Table1 extends TableBase {
 
     @Override
     public List<Var> getVars() {
-        List<Var> x = new ArrayList<>() ;
-        x.add(var) ;
-        return x ;
+        List<Var> x = new ArrayList<>();
+        row.forEach((v,n)->x.add(v));
+        return x;
     }
 
     @Override
     public List<String> getVarNames() {
         List<String> x = new ArrayList<>() ;
-        x.add(var.getVarName()) ;
+        row.forEach((v,n)->x.add(v.getName()));
         return x ;
     }
 
@@ -85,6 +83,6 @@ public class Table1 extends TableBase {
 
     @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 19cbadc296..e741351417 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
@@ -49,7 +49,7 @@ import 
org.apache.jena.sparql.syntax.syntaxtransform.UpdateTransformOps;
 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 assumes the Op 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).
@@ -71,7 +71,7 @@ public class Substitute {
      */
     public static Op inject(Op opInput, Binding binding) {
         Set<Var> injectVars = binding.varsMentioned();
-        Transform transform = new QueryIterLateral.TransformInject(injectVars, 
binding::get);
+        Transform transform = new QueryIterLateral.TransformInject(injectVars, 
binding);
         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 1162c6cb80..9ce2ce85a1 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.atlas.lib.SetUtils;
 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 class QueryIterLateral extends QueryIterRepeatApply {
         private final Set<Var> injectVars;
         private final Set<Node> varsAsNodes;
         private final Function<Var, Node> replacement;
+        private final Binding binding;
         private static final boolean substitute = true;
 
-        // Replacement becomes binding.??
-        // Or "op call injection"!!
-        public TransformInject(Set<Var> injectVars, Function<Var, Node> 
replacement) {
+        public TransformInject(Set<Var> 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 class QueryIterLateral extends QueryIterRepeatApply {
 //            Basic Graph Pattern Matching
 //            Property Path Patterns
 //            evaluation of algebra form Graph(var,P) involving a variable 
(from the syntax GRAPH ?variable {&hellip;})
+        // and also nested (table unit) inside (extend)
 
         @Override
         public Op transform(OpPath opPath) {
@@ -270,6 +275,36 @@ public class QueryIterLateral extends QueryIterRepeatApply 
{
             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<Var> 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<Var, Node> 
replacement) {
             Node s2 = applyReplacement(triple.getSubject(), replacement);
             Node p2 = applyReplacement(triple.getPredicate(), replacement);
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/exec/TS_ExecSPARQL.java 
b/jena-arq/src/test/java/org/apache/jena/sparql/exec/TS_ExecSPARQL.java
index 6ae60d2e42..6a1739a19a 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/exec/TS_ExecSPARQL.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/exec/TS_ExecSPARQL.java
@@ -25,8 +25,9 @@ import org.junit.runners.Suite;
 @Suite.SuiteClasses( {
     TestExecEnvironment.class
     , TestQueryExecDataset.class
+    , TestQueryExecution.class
 } )
- 
+
 public class TS_ExecSPARQL {
 
 }
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/exec/TestQueryExecution.java 
b/jena-arq/src/test/java/org/apache/jena/sparql/exec/TestQueryExecution.java
new file mode 100644
index 0000000000..258a3a003f
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/exec/TestQueryExecution.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.exec;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.Test;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
+import org.apache.jena.sparql.engine.binding.Binding;
+
+/** Miscellaneous tests, e.g. from reports. */
+public class TestQueryExecution {
+    @Test public void lateral_with_join() {
+        // GH-2896 LATERAL
+        String qsReport = """
+            SELECT * {
+                BIND( 'x' AS ?xIn )
+                LATERAL {
+                    VALUES ?x { 1 }
+                    { SELECT ?xIn ?xOut { BIND(?xIn AS ?xOut) } }
+                }
+            }
+            """;
+        DatasetGraph dsg = DatasetGraphFactory.empty();
+        RowSet rowSet = QueryExec.dataset(dsg).query(qsReport).select();
+        Binding row = rowSet.next();
+        row.contains("xOut");
+        Node x = row.get("xOut");
+        assertEquals("x", x.getLiteralLexicalForm());
+    }
+}
diff --git a/jena-cmds/src/main/java/arq/cmdline/ModEngine.java 
b/jena-cmds/src/main/java/arq/cmdline/ModEngine.java
index c278ef2f45..bb6b4b6028 100644
--- a/jena-cmds/src/main/java/arq/cmdline/ModEngine.java
+++ b/jena-cmds/src/main/java/arq/cmdline/ModEngine.java
@@ -44,24 +44,25 @@ public class ModEngine extends ModBase
     private boolean timing = false ;
 
     @Override
-    public void registerWith(CmdGeneral cmdLine)
-    {
-        cmdLine.getUsage().startCategory("Query Engine") ;
-        cmdLine.add(engineDecl, "--engine=EngineName", "Register another 
engine factory[ref]") ;
-        cmdLine.add(unEngineDecl, "--unengine=EngineName", "Unregister an 
engine factory") ;
+    public void registerWith(CmdGeneral cmdLine) {
+        cmdLine.getUsage().startCategory("Query Engine");
+        cmdLine.add(engineDecl, "--engine=EngineName", "Register another 
engine factory[ref]");
+        cmdLine.add(unEngineDecl, "--unengine=EngineName", "Unregister an 
engine factory");
     }
 
-    public void checkCommandLine(CmdGeneral cmdLine)
-    {}
+    public void resetRegistrations() {
+        QueryEngineRef.unregister();
+        QueryEngineRefQuad.unregister();
+        QueryEngineMainQuad.unregister();
+    }
 
     @Override
-    public void processArgs(CmdArgModule cmdLine)
-    {
+    public void processArgs(CmdArgModule cmdLine) {
 
-        List<String> engineDecls = cmdLine.getValues(engineDecl) ;
+        List<String> engineDecls = cmdLine.getValues(engineDecl);
 
-//        if ( x.size() > 0 )
-//            QueryEngineRegistry.get().factories().clear() ;
+        // if ( x.size() > 0 )
+        // QueryEngineRegistry.get().factories().clear() ;
 
         for ( String engineName : engineDecls ) {
             switch (engineName.toLowerCase()) {
@@ -75,7 +76,7 @@ public class ModEngine extends ModBase
             }
         }
 
-        List<String> unEngineDecls = cmdLine.getValues(unEngineDecl) ;
+        List<String> unEngineDecls = cmdLine.getValues(unEngineDecl);
         for ( String engineName : unEngineDecls ) {
             switch (engineName.toLowerCase()) {
                 case "reference", "ref" -> QueryEngineRef.unregister();
diff --git a/jena-cmds/src/main/java/arq/query.java 
b/jena-cmds/src/main/java/arq/query.java
index e3e7a6c75e..f08f250f52 100644
--- a/jena-cmds/src/main/java/arq/query.java
+++ b/jena-cmds/src/main/java/arq/query.java
@@ -61,28 +61,27 @@ public class query extends CmdARQ
     protected ModResultsOut modResults =  new ModResultsOut() ;
     protected ModEngine     modEngine =   new ModEngine() ;
 
-    public static void main (String... argv)
-    {
-        new query(argv).mainRun() ;
+    public static void main(String...argv) {
+        new query(argv).mainRun();
     }
 
-    public query(String[] argv)
-    {
-        super(argv) ;
-        modQuery = new ModQueryIn(getDefaultSyntax()) ;
-        modDataset = setModDataset() ;
+    public query(String[] argv) {
+        super(argv);
+        modQuery = new ModQueryIn(getDefaultSyntax());
+        modDataset = setModDataset();
         modVersion.addClass(null, Jena.class);
 
-        super.addModule(modQuery) ;
-        super.addModule(modResults) ;
-        super.addModule(modDataset) ;
-        super.addModule(modEngine) ;
-        super.addModule(modTime) ;
+        super.addModule(modQuery);
+        super.addModule(modResults);
+        super.addModule(modDataset);
+        super.addModule(modEngine);
+        super.addModule(modTime);
 
-        super.getUsage().startCategory("Control") ;
-        super.add(argExplain,  "--explain", "Explain and log query execution") 
;
-        super.add(argRepeat,   "--repeat=N or N,M", "Do N times or N warmup 
and then M times (use for timing to overcome start up costs of Java)");
-        super.add(argOptimize, "--optimize=", "Turn the query optimizer on or 
off (default: on)") ;
+        super.getUsage().startCategory("Control");
+        super.add(argExplain, "--explain", "Explain and log query execution");
+        super.add(argRepeat, "--repeat=N or N,M",
+                  "Do N times or N warmup and then M times (use for timing to 
overcome start up costs of Java)");
+        super.add(argOptimize, "--optimize=", "Turn the query optimizer on or 
off (default: on)");
     }
 
     /** Default syntax used when the syntax can not be determined from the 
command name or file extension
@@ -163,6 +162,7 @@ public class query extends CmdARQ
             String avgStr = modTime.timeStr(avg) ;
             System.err.println("Total time: "+modTime.timeStr(totalTime)+" sec 
for repeat count of "+repeatCount+ " : average: "+avgStr) ;
         }
+        modEngine.resetRegistrations();
     }
 
     @Override
@@ -211,8 +211,7 @@ public class query extends CmdARQ
     }
 
     protected long totalTime = 0 ;
-    protected void queryExec(boolean timed, ResultsFormat fmt, PrintStream 
resultsDest)
-    {
+    protected void queryExec(boolean timed, ResultsFormat fmt, PrintStream 
resultsDest) {
         try {
             Query query = getQuery() ;
             if ( isVerbose() ) {

Reply via email to