Repository: jena Updated Branches: refs/heads/master fc7fdb3ed -> b5d0c49d6
Support transforming ORDER BY conditions in QueryTransformOps Project: http://git-wip-us.apache.org/repos/asf/jena/repo Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/b5d0c49d Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/b5d0c49d Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/b5d0c49d Branch: refs/heads/master Commit: b5d0c49d6d12dd70e38113f1c3cd338b605e9b0a Parents: fc7fdb3 Author: Rob Vesse <rve...@apache.org> Authored: Mon Oct 17 12:07:46 2016 +0100 Committer: Rob Vesse <rve...@apache.org> Committed: Mon Oct 17 12:07:46 2016 +0100 ---------------------------------------------------------------------- .../syntaxtransform/QueryTransformOps.java | 258 ++++++++++--------- .../syntaxtransform/TestSyntaxTransform.java | 5 + 2 files changed, 142 insertions(+), 121 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jena/blob/b5d0c49d/jena-arq/src/main/java/org/apache/jena/sparql/syntax/syntaxtransform/QueryTransformOps.java ---------------------------------------------------------------------- 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 b08641a..4e772b9 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 @@ -16,244 +16,260 @@ * limitations under the License. */ -package org.apache.jena.sparql.syntax.syntaxtransform ; - -import java.util.List ; -import java.util.Map ; - -import org.apache.jena.graph.Node ; -import org.apache.jena.query.Query ; -import org.apache.jena.query.QueryVisitor ; -import org.apache.jena.query.SortCondition ; -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.DatasetDescription ; -import org.apache.jena.sparql.core.Prologue ; -import org.apache.jena.sparql.core.Var ; -import org.apache.jena.sparql.core.VarExprList ; -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.graph.NodeTransform ; -import org.apache.jena.sparql.syntax.Element ; -import org.apache.jena.sparql.syntax.ElementGroup ; - -/** Support for transformation of query abstract syntax. */ +package org.apache.jena.sparql.syntax.syntaxtransform; + +import java.util.List; +import java.util.Map; + +import org.apache.jena.graph.Node; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryVisitor; +import org.apache.jena.query.SortCondition; +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.DatasetDescription; +import org.apache.jena.sparql.core.Prologue; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.core.VarExprList; +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.graph.NodeTransform; +import org.apache.jena.sparql.syntax.Element; +import org.apache.jena.sparql.syntax.ElementGroup; + +/** Support for transformation of query abstract syntax. */ public class QueryTransformOps { public static Query transform(Query query, Map<Var, ? extends Node> substitutions) { - ElementTransform eltrans = new ElementTransformSubst(substitutions) ; - NodeTransform nodeTransform = new NodeTransformSubst(substitutions) ; - ExprTransform exprTrans = new ExprTransformNodeElement(nodeTransform, eltrans) ; - return transform(query, eltrans, exprTrans) ; + ElementTransform eltrans = new ElementTransformSubst(substitutions); + NodeTransform nodeTransform = new NodeTransformSubst(substitutions); + ExprTransform exprTrans = new ExprTransformNodeElement(nodeTransform, eltrans); + return transform(query, eltrans, exprTrans); } public static Query transform(Query query, ElementTransform transform, ExprTransform exprTransform) { - Query q2 = QueryTransformOps.shallowCopy(query) ; + Query q2 = QueryTransformOps.shallowCopy(query); // "Shallow copy with transform." - transformVarExprList(q2.getProject(), exprTransform) ; - transformVarExprList(q2.getGroupBy(), exprTransform) ; - transformExprList(q2.getHavingExprs(), exprTransform) ; - //?? DOES NOT WORK: transformExprListAgg(q2.getAggregators(), exprTransform) ; - // ?? - // Nothing to do about ORDER BY - leave to sort by that variable. - -// if ( q2.hasHaving() ) {} -// if ( q2.hasAggregators() ) {} - - Element el = q2.getQueryPattern() ; - Element el2 = ElementTransformer.transform(el, transform, exprTransform) ; + transformVarExprList(q2.getProject(), exprTransform); + transformVarExprList(q2.getGroupBy(), exprTransform); + transformExprList(q2.getHavingExprs(), exprTransform); + // ?? DOES NOT WORK: transformExprListAgg(q2.getAggregators(), + // exprTransform) ; + // ?? + if (q2.getOrderBy() != null) { + transformSortConditions(q2.getOrderBy(), exprTransform); + } + + // if ( q2.hasHaving() ) {} + // if ( q2.hasAggregators() ) {} + + Element el = q2.getQueryPattern(); + Element el2 = ElementTransformer.transform(el, transform, exprTransform); // Top level is always a group. - if ( ! ( el2 instanceof ElementGroup ) ) { - ElementGroup eg = new ElementGroup() ; + if (!(el2 instanceof ElementGroup)) { + ElementGroup eg = new ElementGroup(); eg.addElement(el2); - el2 = eg ; + el2 = eg; } - q2.setQueryPattern(el2) ; - return q2 ; + q2.setQueryPattern(el2); + return q2; } public static Query transform(Query query, ElementTransform transform) { - ExprTransform noop = new ExprTransformApplyElementTransform(transform) ; - return transform(query, transform, noop) ; + ExprTransform noop = new ExprTransformApplyElementTransform(transform); + return transform(query, transform, noop); } // ** Mutates the List private static void transformExprList(List<Expr> exprList, ExprTransform exprTransform) { - for ( int i = 0 ; i < exprList.size() ; i++ ) { - Expr e1 = exprList.get(0) ; - Expr e2 = ExprTransformer.transform(exprTransform, e1) ; - if ( e2 == null || e2 == e1 ) - continue ; - exprList.set(i, e2) ; + for (int i = 0; i < exprList.size(); i++) { + Expr e1 = exprList.get(0); + Expr e2 = ExprTransformer.transform(exprTransform, e1); + if (e2 == null || e2 == e1) + continue; + exprList.set(i, e2); + } + } + + private static void transformSortConditions(List<SortCondition> conditions, ExprTransform exprTransform) { + for (int i = 0; i < conditions.size(); i++) { + SortCondition s1 = conditions.get(i); + Expr e = ExprTransformer.transform(exprTransform, s1.expression); + if (e == null || s1.expression.equals(e)) + continue; + conditions.set(i, new SortCondition(e, s1.direction)); } } // ** Mutates the VarExprList private static void transformVarExprList(VarExprList varExprList, ExprTransform exprTransform) { - Map<Var, Expr> map = varExprList.getExprs() ; + Map<Var, Expr> map = varExprList.getExprs(); for (Var v : varExprList.getVars()) { - Expr e = varExprList.getExpr(v) ; - ExprVar ev = new ExprVar(v) ; - Expr ev2 = exprTransform.transform(ev) ; - if ( ev != ev2 ) { - if ( e != null ) - throw new ARQException("Can't substitute " + v + " because it's used as an AS variable") ; - if ( ev2.isConstant() || ev2.isVariable() ) { + Expr e = varExprList.getExpr(v); + ExprVar ev = new ExprVar(v); + Expr ev2 = exprTransform.transform(ev); + if (ev != ev2) { + if (e != null) + throw new ARQException("Can't substitute " + v + " because it's used as an AS variable"); + if (ev2.isConstant() || ev2.isVariable()) { // Convert to (substitute value AS ?var) - map.put(v, ev2) ; - continue ; - } - else - throw new ARQException("Can't substitute " + v + " because it's not a simple value: " + ev2) ; + map.put(v, ev2); + continue; + } else + throw new ARQException("Can't substitute " + v + " because it's not a simple value: " + ev2); } - if ( e == null ) - continue ; + if (e == null) + continue; // Didn't change the variable. - Expr e2 = ExprTransformer.transform(exprTransform, e) ; - if ( e != e2 ) + Expr e2 = ExprTransformer.transform(exprTransform, e); + if (e != e2) // replace - map.put(v, e2) ; + map.put(v, e2); } } static class QueryShallowCopy implements QueryVisitor { - final Query newQuery = new Query() ; + final Query newQuery = new Query(); - QueryShallowCopy() {} + QueryShallowCopy() { + } @Override public void startVisit(Query query) { - newQuery.setSyntax(query.getSyntax()) ; + newQuery.setSyntax(query.getSyntax()); - if ( query.explicitlySetBaseURI() ) - newQuery.setBaseURI(query.getPrologue().getResolver()) ; + if (query.explicitlySetBaseURI()) + newQuery.setBaseURI(query.getPrologue().getResolver()); - newQuery.setQueryResultStar(query.isQueryResultStar()) ; + newQuery.setQueryResultStar(query.isQueryResultStar()); - if ( query.hasDatasetDescription() ) { - DatasetDescription desc = query.getDatasetDescription() ; + if (query.hasDatasetDescription()) { + DatasetDescription desc = query.getDatasetDescription(); for (String x : desc.getDefaultGraphURIs()) - newQuery.addGraphURI(x) ; + newQuery.addGraphURI(x); for (String x : desc.getDefaultGraphURIs()) - newQuery.addNamedGraphURI(x) ; + newQuery.addNamedGraphURI(x); } - + // Aggregators. - newQuery.getAggregators().addAll(query.getAggregators()) ; + newQuery.getAggregators().addAll(query.getAggregators()); } @Override public void visitPrologue(Prologue prologue) { // newQuery.setBaseURI(prologue.getResolver()) ; - PrefixMapping pmap = new PrefixMappingImpl().setNsPrefixes(prologue.getPrefixMapping()) ; - newQuery.setPrefixMapping(pmap) ; + PrefixMapping pmap = new PrefixMappingImpl().setNsPrefixes(prologue.getPrefixMapping()); + newQuery.setPrefixMapping(pmap); } @Override - public void visitResultForm(Query q) {} + public void visitResultForm(Query q) { + } @Override public void visitSelectResultForm(Query query) { - newQuery.setQuerySelectType() ; - newQuery.setDistinct(query.isDistinct()) ; - VarExprList x = query.getProject() ; + newQuery.setQuerySelectType(); + newQuery.setDistinct(query.isDistinct()); + VarExprList x = query.getProject(); for (Var v : x.getVars()) { - Expr expr = x.getExpr(v) ; - if ( expr == null ) - newQuery.addResultVar(v) ; + Expr expr = x.getExpr(v); + if (expr == null) + newQuery.addResultVar(v); else - newQuery.addResultVar(v, expr) ; + newQuery.addResultVar(v, expr); } } @Override public void visitConstructResultForm(Query query) { - newQuery.setQueryConstructType() ; - newQuery.setConstructTemplate(query.getConstructTemplate()) ; + newQuery.setQueryConstructType(); + newQuery.setConstructTemplate(query.getConstructTemplate()); } @Override public void visitDescribeResultForm(Query query) { - newQuery.setQueryDescribeType() ; + newQuery.setQueryDescribeType(); for (Node x : query.getResultURIs()) - newQuery.addDescribeNode(x) ; + newQuery.addDescribeNode(x); } @Override public void visitAskResultForm(Query query) { - newQuery.setQueryAskType() ; + newQuery.setQueryAskType(); } @Override - public void visitDatasetDecl(Query query) {} + public void visitDatasetDecl(Query query) { + } @Override public void visitQueryPattern(Query query) { - newQuery.setQueryPattern(query.getQueryPattern()) ; + newQuery.setQueryPattern(query.getQueryPattern()); } @Override public void visitGroupBy(Query query) { - if ( query.hasGroupBy() ) { - VarExprList x = query.getGroupBy() ; + if (query.hasGroupBy()) { + VarExprList x = query.getGroupBy(); for (Var v : x.getVars()) { - Expr expr = x.getExpr(v) ; - if ( expr == null ) - newQuery.addGroupBy(v) ; + Expr expr = x.getExpr(v); + if (expr == null) + newQuery.addGroupBy(v); else - newQuery.addGroupBy(v, expr) ; + newQuery.addGroupBy(v, expr); } } } @Override public void visitHaving(Query query) { - if ( query.hasHaving() ) { + if (query.hasHaving()) { for (Expr expr : query.getHavingExprs()) - newQuery.addHavingCondition(expr) ; + newQuery.addHavingCondition(expr); } } @Override public void visitOrderBy(Query query) { - if ( query.hasOrderBy() ) { + if (query.hasOrderBy()) { for (SortCondition sc : query.getOrderBy()) - newQuery.addOrderBy(sc) ; + newQuery.addOrderBy(sc); } } @Override public void visitLimit(Query query) { - newQuery.setLimit(query.getLimit()) ; + newQuery.setLimit(query.getLimit()); } @Override public void visitOffset(Query query) { - newQuery.setOffset(query.getOffset()) ; + newQuery.setOffset(query.getOffset()); } @Override public void visitValues(Query query) { - if ( query.hasValues() ) - newQuery.setValuesDataBlock(query.getValuesVariables(), query.getValuesData()) ; + if (query.hasValues()) + newQuery.setValuesDataBlock(query.getValuesVariables(), query.getValuesData()); } @Override - public void finishVisit(Query query) {} + public void finishVisit(Query query) { + } } public static Query shallowCopy(Query query) { - QueryShallowCopy copy = new QueryShallowCopy() ; - query.visit(copy) ; - Query q2 = copy.newQuery ; - return q2 ; + QueryShallowCopy copy = new QueryShallowCopy(); + query.visit(copy); + Query q2 = copy.newQuery; + return q2; } } http://git-wip-us.apache.org/repos/asf/jena/blob/b5d0c49d/jena-arq/src/test/java/org/apache/jena/sparql/syntax/syntaxtransform/TestSyntaxTransform.java ---------------------------------------------------------------------- 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 23d9f9b..f5910c8 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 @@ -90,6 +90,11 @@ public class TestSyntaxTransform extends BaseTest testQuery("SELECT * { ?s ?p ?srv SERVICE ?srv { ?s ?p ?srv}}", "SELECT * { ?s ?p <urn:service> SERVICE <urn:service> { ?s ?p <urn:service>}}", "srv", "<urn:service>") ; } + + @Test public void subst_query_30() { + testQuery("SELECT * { ?s ?p ?o } ORDER BY ?s", "SELECT * { <urn:x> ?p ?o } ORDER BY (<urn:x>)", + "s", "<urn:x>"); + } @Test public void subst_update_01() {