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
commit f63360c4f052eb5e0529a1b256f7cbdcb82c0bce Author: Andy Seaborne <[email protected]> AuthorDate: Tue Aug 20 22:19:43 2024 +0100 GH-2650: Fix for substitution into aggregates --- .../syntaxtransform/ExprTransformNodeElement.java | 65 ++++++++++++---------- .../syntax/syntaxtransform/QueryTransformOps.java | 15 ++--- .../apache/jena/sparql/algebra/TestOpAsQuery.java | 42 +++++++------- .../syntaxtransform/TestSyntaxTransform.java | 21 +++++++ 4 files changed, 84 insertions(+), 59 deletions(-) diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/ExprTransformNodeElement.java b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/ExprTransformNodeElement.java index 7da7057fd0..ea7eca93ad 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/ExprTransformNodeElement.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/ExprTransformNodeElement.java @@ -16,72 +16,77 @@ * limitations under the License. */ -package org.apache.jena.sparql.syntax.syntaxtransform ; +package org.apache.jena.sparql.syntax.syntaxtransform; -import org.apache.jena.atlas.lib.InternalErrorException ; -import org.apache.jena.graph.Node ; -import org.apache.jena.sparql.algebra.Op ; -import org.apache.jena.sparql.core.Var ; -import org.apache.jena.sparql.expr.* ; -import org.apache.jena.sparql.graph.NodeTransform ; -import org.apache.jena.sparql.syntax.Element ; -import org.apache.jena.sparql.syntax.ElementVisitor ; +import org.apache.jena.atlas.lib.InternalErrorException; +import org.apache.jena.graph.Node; +import org.apache.jena.sparql.algebra.Op; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.expr.*; +import org.apache.jena.sparql.graph.NodeTransform; +import org.apache.jena.sparql.syntax.Element; +import org.apache.jena.sparql.syntax.ElementVisitor; /** * Special version of ExprTransform for applying a node transform on syntax * (Elements) only */ public class ExprTransformNodeElement extends ExprTransformCopy { - private final NodeTransform nodeTransform ; - private final ElementTransform elementTransform ; + private final NodeTransform nodeTransform; + private final ElementTransform elementTransform; private final ElementVisitor beforeVisitor; private final ElementVisitor afterVisitor; public ExprTransformNodeElement(NodeTransform nodeTransform, ElementTransform eltrans) { - this(nodeTransform, eltrans, null, null) ; + this(nodeTransform, eltrans, null, null); } public ExprTransformNodeElement(NodeTransform nodeTransform, ElementTransform eltrans, ElementVisitor beforeVisitor, ElementVisitor afterVisitor) { - this.nodeTransform = nodeTransform ; - this.elementTransform = eltrans ; - this.beforeVisitor = beforeVisitor ; - this.afterVisitor = afterVisitor ; + this.nodeTransform = nodeTransform; + this.elementTransform = eltrans; + this.beforeVisitor = beforeVisitor; + this.afterVisitor = afterVisitor; } @Override public Expr transform(ExprVar nv) { - Node n = nodeTransform.apply(nv.getAsNode()) ; + Node n = nodeTransform.apply(nv.getAsNode()); if ( n == nv.getAsNode() ) - return nv ; + return nv; if ( n instanceof Var ) { - Var v = Var.alloc(n) ; - return new ExprVar(v) ; + Var v = Var.alloc(n); + return new ExprVar(v); } - return NodeValue.makeNode(n) ; + return NodeValue.makeNode(n); } @Override public Expr transform(NodeValue nv) { - Node n = nodeTransform.apply(nv.asNode()) ; + Node n = nodeTransform.apply(nv.asNode()); if ( n == nv.asNode() ) - return nv ; - return NodeValue.makeNode(n) ; + return nv; + return NodeValue.makeNode(n); } @Override public Expr transform(ExprFunctionOp funcOp, ExprList args, Op opArg) { // Syntax phased only - ignore args and opArg - Element elt = funcOp.getElement() ; - Element elt1 = ElementTransformer.transform(elt, elementTransform, this, beforeVisitor, afterVisitor) ; + Element elt = funcOp.getElement(); + Element elt1 = ElementTransformer.transform(elt, elementTransform, this, beforeVisitor, afterVisitor); if ( elt == elt1 ) - return funcOp ; + return funcOp; else { if ( funcOp instanceof E_Exists ) - return new E_Exists(elt1) ; + return new E_Exists(elt1); if ( funcOp instanceof E_NotExists ) - return new E_NotExists(elt1) ; - throw new InternalErrorException("Unknown ExprFunctionOp: " + funcOp.getFunctionSymbol()) ; + return new E_NotExists(elt1); + throw new InternalErrorException("Unknown ExprFunctionOp: " + funcOp.getFunctionSymbol()); } } + + @Override + public Expr transform(ExprAggregator eAgg) { + return eAgg.applyNodeTransform(nodeTransform); + } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java index b461a0a7e0..313f75245b 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java @@ -36,10 +36,7 @@ import org.apache.jena.shared.PrefixMapping; import org.apache.jena.shared.impl.PrefixMappingImpl; import org.apache.jena.sparql.ARQException; import org.apache.jena.sparql.core.*; -import org.apache.jena.sparql.expr.Expr; -import org.apache.jena.sparql.expr.ExprTransform; -import org.apache.jena.sparql.expr.ExprTransformer; -import org.apache.jena.sparql.expr.ExprVar; +import org.apache.jena.sparql.expr.*; import org.apache.jena.sparql.graph.NodeTransform; import org.apache.jena.sparql.modify.request.QuadAcc; import org.apache.jena.sparql.syntax.*; @@ -82,6 +79,7 @@ public class QueryTransformOps { // Reset internal to only what now can be seen. q2.resetResultVars(); } + setAggregators(q2, query, exprTransform); return q2; } @@ -111,6 +109,12 @@ public class QueryTransformOps { } } + private static void setAggregators(Query newQuery, Query query, ExprTransform exprTransform) { + for (ExprAggregator aggregator : query.getAggregators()) { + newQuery.getAggregators().add((ExprAggregator) exprTransform.transform(aggregator)); + } + } + // Do the result form part of the cloned query. private static void mutateByQueryType(Query q2, ElementTransform transform, ExprTransform exprTransform) { switch(q2.queryType()) { @@ -300,9 +304,6 @@ public class QueryTransformOps { for (String x : desc.getNamedGraphURIs()) newQuery.addNamedGraphURI(x); } - - // Aggregators. - newQuery.getAggregators().addAll(query.getAggregators()); } @Override diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java index 0004bcc172..3d91b293b9 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java @@ -344,28 +344,26 @@ public class TestOpAsQuery { @Test public void testAggregatesInSubQuery3() { - //Actual test case from JENA-445 bug report - String queryString = - "PREFIX dcterms: <http://purl.org/dc/terms/> \n" + - "PREFIX dbpedia: <http://dbpedia.org/resource/> \n" + - - "SELECT ?num_of_holidays ?celebrate_Chinese_New_Year WHERE { \n" + - "{" + - "SELECT ?country_cat (COUNT(?holiday) as ?num_of_holidays) \n" + - "WHERE {" + - "?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. \n" + - "?holiday dcterms:subject ?country_cat \n" + - "}GROUP by ?country_cat \n" + - "} \n" + - "{ \n" + - "SELECT ?country_cat (COUNT(?holiday) as ?celebrate_Chinese_New_Year) \n" + - "WHERE { \n" + - "?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. \n" + - "?holiday dcterms:subject ?country_cat \n" + - "FILTER(?holiday=\"http://dbpedia.org/resource/Lunar_New_Year\'s_Day\") \n" + - "}GROUP by ?country_cat \n" + - "} \n" + - "}\n"; + String queryString = """ + PREFIX dcterms: <http://purl.org/dc/terms/> + PREFIX dbpedia: <http://dbpedia.org/resource/> + + SELECT ?num_of_holidays ?celebrate_Chinese_New_Year WHERE { + { + SELECT ?country_cat (COUNT(?holiday) as ?num_of_holidays) WHERE { + ?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. + ?holiday dcterms:subject ?country_cat + } GROUP by ?country_cat + } + { + SELECT ?country_cat (COUNT(?holiday) as ?celebrate_Chinese_New_Year) WHERE { + ?country_cat <http://www.w3.org/2004/02/skos/core#broader> <http://dbpedia.org/resource/Category:Public_holidays_by_country>. + ?holiday dcterms:subject ?country_cat + FILTER(?holiday="http://dbpedia.org/resource/Lunar_New_Year's_Day") + } GROUP by ?country_cat + } + } + """; test_roundTripQuery(queryString); } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestSyntaxTransform.java b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestSyntaxTransform.java index 1c93d54e9d..f05e19c005 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestSyntaxTransform.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestSyntaxTransform.java @@ -96,6 +96,27 @@ public class TestSyntaxTransform "s", "<urn:ex:z>"); } + // GH-2650 + @Test public void subst_query_31() { + testQuery("PREFIX : <http://example/> SELECT (SUM(?a + ?b) AS ?c) WHERE { ?s :p ?a }", + "PREFIX : <http://example/> SELECT (SUM(123 + ?b) AS ?c) WHERE { ?s :p 123 }", + "a", "123"); + } + + // GH-2650 + @Test public void subst_query_32() { + testQuery("PREFIX : <http://example/> SELECT (SUM(?a + ?b) AS ?c) WHERE { }", + "PREFIX : <http://example/> SELECT (SUM(123 + ?b) AS ?c) WHERE { }", + "a", "123"); + } + + // GH-2650 + @Test public void subst_query_33() { + testQuery("SELECT * WHERE { ?s ?p ?o { SELECT (count(?a) as ?C) WHERE {} } }", + "SELECT * WHERE { ?s ?p ?o { SELECT (count(123) as ?C) WHERE {} } }", + "a", "123"); + } + // Same except use the Model API. @Test public void subst_query_model_2() { testQueryModel("SELECT * { ?s ?p ?o } ORDER BY ?s",
