Repository: jena Updated Branches: refs/heads/master 65e7b0f0e -> bb30cae54
Fixed for the reopened JENA-1144 Fixed the projection of the aggregate methods in the SelectHandler. Project: http://git-wip-us.apache.org/repos/asf/jena/repo Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/bb30cae5 Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/bb30cae5 Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/bb30cae5 Branch: refs/heads/master Commit: bb30cae5463df38913f9677cc040557f24cb3924 Parents: 65e7b0f Author: Claude Warren <[email protected]> Authored: Sat Mar 5 18:30:44 2016 +0000 Committer: Claude Warren <[email protected]> Committed: Sat Mar 5 18:30:44 2016 +0000 ---------------------------------------------------------------------- .../querybuilder/handlers/SelectHandler.java | 27 +++- .../arq/querybuilder/SelectBuilderTest.java | 156 +++++++++++-------- 2 files changed, 118 insertions(+), 65 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jena/blob/bb30cae5/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java ---------------------------------------------------------------------- diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java index 2d0904b..a2982e6 100644 --- a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java +++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java @@ -20,6 +20,7 @@ package org.apache.jena.arq.querybuilder.handlers; import java.io.StringReader; import java.util.List; import java.util.Map; +import java.util.HashMap; import org.apache.jena.graph.Node; import org.apache.jena.query.Query; @@ -27,6 +28,7 @@ import org.apache.jena.query.QueryParseException; 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.ExprAggregator; import org.apache.jena.sparql.lang.arq.ARQParser; import org.apache.jena.sparql.lang.arq.ParseException; import org.apache.jena.sparql.lang.arq.TokenMgrError; @@ -40,6 +42,8 @@ public class SelectHandler implements Handler { // the query to handle private final Query query; + private final Map<Var, ExprAggregator> aggregators = new HashMap<Var, ExprAggregator>(); + /** * Constructor. * @@ -113,9 +117,12 @@ public class SelectHandler implements Handler { * Parse an expression string into an expression. * * This must be able to be parsed as though it were written "SELECT "+s - * @param s the select string to parse. + * + * @param s + * the select string to parse. * @return the epxression - * @throws QueryParseException on error + * @throws QueryParseException + * on error */ private Expr parseExpr(String s) throws QueryParseException { try { @@ -155,6 +162,9 @@ public class SelectHandler implements Handler { } query.setQueryResultStar(false); query.addResultVar(var, expr); + if (expr instanceof ExprAggregator) { + aggregators.put(var, (ExprAggregator) expr); + } } /** @@ -194,6 +204,9 @@ public class SelectHandler implements Handler { qProjectVars.add(var, shProjectVars.getExpr(var)); } } + for (Var v : selectHandler.aggregators.keySet()) { + aggregators.put(v, selectHandler.aggregators.get(v)); + } } @Override @@ -206,6 +219,16 @@ public class SelectHandler implements Handler { if (query.getProject().getVars().isEmpty()) { query.setQueryResultStar(true); } + + VarExprList vel = query.getProject(); + Map<Var, Expr> exprMap = vel.getExprs(); + + for (Map.Entry<Var, ExprAggregator> entry : aggregators.entrySet()) { + Expr expr = query.allocAggregate(entry.getValue().getAggregator()); + if (exprMap.containsKey(entry.getKey())) { + exprMap.put(entry.getKey(), expr); + } + } // handle the SELECT * case query.getProjectVars(); } http://git-wip-us.apache.org/repos/asf/jena/blob/bb30cae5/jena-extras/jena-querybuilder/src/test/java/org/apache/jena/arq/querybuilder/SelectBuilderTest.java ---------------------------------------------------------------------- diff --git a/jena-extras/jena-querybuilder/src/test/java/org/apache/jena/arq/querybuilder/SelectBuilderTest.java b/jena-extras/jena-querybuilder/src/test/java/org/apache/jena/arq/querybuilder/SelectBuilderTest.java index 535be17..54c76cf 100644 --- a/jena-extras/jena-querybuilder/src/test/java/org/apache/jena/arq/querybuilder/SelectBuilderTest.java +++ b/jena-extras/jena-querybuilder/src/test/java/org/apache/jena/arq/querybuilder/SelectBuilderTest.java @@ -18,20 +18,29 @@ package org.apache.jena.arq.querybuilder; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.apache.jena.arq.AbstractRegexpBasedTest; -import org.apache.jena.sparql.core.Var ; -import org.apache.jena.vocabulary.RDF ; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.lang.sparql_11.ParseException; +import org.apache.jena.vocabulary.RDF; import org.junit.Before; import org.junit.Test; public class SelectBuilderTest extends AbstractRegexpBasedTest { private SelectBuilder builder; - - @Before + + @Before public void setup() { builder = new SelectBuilder(); } @@ -40,23 +49,18 @@ public class SelectBuilderTest extends AbstractRegexpBasedTest { public void testSelectAsterisk() { builder.addVar("*").addWhere("?s", "?p", "?o"); - assertContainsRegex(SELECT + "\\*" + SPACE + WHERE + OPEN_CURLY - + var("s") + SPACE + var("p") + SPACE + var("o") + OPT_SPACE - + CLOSE_CURLY, builder.buildString()); + assertContainsRegex(SELECT + "\\*" + SPACE + WHERE + OPEN_CURLY + var("s") + SPACE + var("p") + SPACE + var("o") + + OPT_SPACE + CLOSE_CURLY, builder.buildString()); builder.setVar(Var.alloc("p"), RDF.type); - assertContainsRegex(SELECT + "\\*" + SPACE + WHERE + OPEN_CURLY - + var("s") + SPACE - + regexRDFtype - + SPACE + var("o") + OPT_SPACE + CLOSE_CURLY, - builder.buildString()); + assertContainsRegex(SELECT + "\\*" + SPACE + WHERE + OPEN_CURLY + var("s") + SPACE + regexRDFtype + SPACE + + var("o") + OPT_SPACE + CLOSE_CURLY, builder.buildString()); } @Test public void testAll() { - builder.addVar("s").addPrefix("foaf", "http://xmlns.com/foaf/0.1/") - .addWhere("?s", RDF.type, "foaf:Person") + builder.addVar("s").addPrefix("foaf", "http://xmlns.com/foaf/0.1/").addWhere("?s", RDF.type, "foaf:Person") .addOptional("?s", "foaf:name", "?name").addOrderBy("?s"); String query = builder.buildString(); @@ -67,60 +71,49 @@ public class SelectBuilderTest extends AbstractRegexpBasedTest { * <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> foaf:Person . * OPTIONAL { ?s foaf:name ?name .} } ORDER BY ?s */ - assertContainsRegex(PREFIX + "foaf:" + SPACE - + uri("http://xmlns.com/foaf/0.1/"), query); + assertContainsRegex(PREFIX + "foaf:" + SPACE + uri("http://xmlns.com/foaf/0.1/"), query); assertContainsRegex(SELECT + var("s"), query); - assertContainsRegex(WHERE + OPEN_CURLY + var("s") + SPACE - + regexRDFtype - + SPACE + "foaf:Person" + SPACE + OPTIONAL - + OPEN_CURLY + var("s") + SPACE + "foaf:name" + SPACE - + var("name") + OPT_SPACE + CLOSE_CURLY + assertContainsRegex(WHERE + OPEN_CURLY + var("s") + SPACE + regexRDFtype + SPACE + "foaf:Person" + SPACE + + OPTIONAL + OPEN_CURLY + var("s") + SPACE + "foaf:name" + SPACE + var("name") + OPT_SPACE + CLOSE_CURLY + CLOSE_CURLY, query); assertContainsRegex(ORDER_BY + var("s"), query); builder.setVar("name", "Smith"); query = builder.buildString(); - assertContainsRegex(PREFIX + "foaf:" + SPACE - + uri("http://xmlns.com/foaf/0.1/"), query); + assertContainsRegex(PREFIX + "foaf:" + SPACE + uri("http://xmlns.com/foaf/0.1/"), query); assertContainsRegex(SELECT + var("s"), query); - assertContainsRegex(WHERE + OPEN_CURLY + var("s") + SPACE - + regexRDFtype - + SPACE + "foaf:Person" + SPACE + OPTIONAL - + OPEN_CURLY + var("s") + SPACE + "foaf:name" + SPACE - + quote("Smith") + presentStringType() + assertContainsRegex(WHERE + OPEN_CURLY + var("s") + SPACE + regexRDFtype + SPACE + "foaf:Person" + SPACE + + OPTIONAL + OPEN_CURLY + var("s") + SPACE + "foaf:name" + SPACE + quote("Smith") + presentStringType() + OPT_SPACE + CLOSE_CURLY + CLOSE_CURLY, query); assertContainsRegex(ORDER_BY + var("s"), query); } @Test public void testPredicateVar() { - builder.addVar("*").addPrefix("", "http://example/") - .addWhere(":S", "?p", ":O"); + builder.addVar("*").addPrefix("", "http://example/").addWhere(":S", "?p", ":O"); String query = builder.buildString(); - assertContainsRegex(WHERE + OPEN_CURLY + ":S" + SPACE + var("p") - + SPACE + ":O" + OPT_SPACE + CLOSE_CURLY, query); + assertContainsRegex(WHERE + OPEN_CURLY + ":S" + SPACE + var("p") + SPACE + ":O" + OPT_SPACE + CLOSE_CURLY, + query); } @Test public void testSubjectVar() { - builder.addVar("*").addPrefix("", "http://example/") - .addWhere("?s", ":P", ":O"); + builder.addVar("*").addPrefix("", "http://example/").addWhere("?s", ":P", ":O"); String query = builder.buildString(); - assertContainsRegex(WHERE + OPEN_CURLY + var("s") + SPACE + ":P" - + SPACE + ":O" + OPT_SPACE + CLOSE_CURLY, query); + assertContainsRegex(WHERE + OPEN_CURLY + var("s") + SPACE + ":P" + SPACE + ":O" + OPT_SPACE + CLOSE_CURLY, + query); } @Test public void testObjectVar() { - builder.addVar("*").addPrefix("", "http://example/") - .addWhere(":S", ":P", "?o"); + builder.addVar("*").addPrefix("", "http://example/").addWhere(":S", ":P", "?o"); String query = builder.buildString(); - assertContainsRegex(WHERE + OPEN_CURLY + ":S" + SPACE + ":P" + SPACE - + var("o") + OPT_SPACE + CLOSE_CURLY, query); + assertContainsRegex(WHERE + OPEN_CURLY + ":S" + SPACE + ":P" + SPACE + var("o") + OPT_SPACE + CLOSE_CURLY, + query); } @Test @@ -130,37 +123,74 @@ public class SelectBuilderTest extends AbstractRegexpBasedTest { assertContainsRegex(SELECT + "\\*" + SPACE, query); } - + @Test public void testList() { - builder.addVar( "*" ) - .addWhere( builder.list( "<one>", "?two", "'three'"), "<foo>", "<bar>"); + builder.addVar("*").addWhere(builder.list("<one>", "?two", "'three'"), "<foo>", "<bar>"); String query = builder.buildString(); - - assertContainsRegex( - "_:b0"+SPACE+ uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") + SPACE + uri("one") + SEMI - + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") + SPACE+"_:b1"+ DOT - + SPACE + "_:b1"+SPACE+ uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") + SPACE + var("two") + SEMI - + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") + SPACE+"_:b2"+ DOT - + SPACE + "_:b2"+SPACE+ uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") + SPACE + quote("three") + SEMI - + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") + SPACE +uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil") - , query); - - assertContainsRegex( - "_:b0"+SPACE+ uri("foo") + SPACE + uri("bar"), query); + + assertContainsRegex("_:b0" + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") + SPACE + + uri("one") + SEMI + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") + SPACE + "_:b1" + + DOT + SPACE + "_:b1" + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") + SPACE + + var("two") + SEMI + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") + SPACE + "_:b2" + + DOT + SPACE + "_:b2" + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#first") + SPACE + + quote("three") + SEMI + SPACE + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest") + SPACE + + uri("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"), query); + + assertContainsRegex("_:b0" + SPACE + uri("foo") + SPACE + uri("bar"), query); } - + @Test public void testClone() { - builder.addVar( "*" ) - .addWhere( "?two", "<foo>", "<bar>"); + builder.addVar("*").addWhere("?two", "<foo>", "<bar>"); SelectBuilder builder2 = builder.clone(); - builder2.addOrderBy( "?two"); - + builder2.addOrderBy("?two"); + String q1 = builder.buildString(); String q2 = builder2.buildString(); - - assertTrue( q2.contains("ORDER BY")); - assertFalse( q1.contains("ORDER BY")); + + assertTrue(q2.contains("ORDER BY")); + assertFalse(q1.contains("ORDER BY")); + } + + @Test + public void testAggregatorsInSelect() throws ParseException { + builder.addVar("?x").addVar("count(*)", "?c").addWhere("?x", "?p", "?o").addGroupBy("?x"); + + Model m = ModelFactory.createDefaultModel(); + Resource r = m.createResource("urn:one"); + m.add(r, m.getProperty("urn:p:one"), m.createTypedLiteral(1)); + m.add(r, m.getProperty("urn:p:two"), m.createTypedLiteral(3)); + m.add(r, m.getProperty("urn:p:three"), m.createTypedLiteral(5)); + r = m.createResource("urn:two"); + m.add(r, m.getProperty("urn:p:one"), m.createTypedLiteral(1)); + m.add(r, m.getProperty("urn:p:two"), m.createTypedLiteral(3)); + m.add(r, m.getProperty("urn:p:three"), m.createTypedLiteral(5)); + + QueryExecution qexec = QueryExecutionFactory.create(builder.build(), m); + + ResultSet results = qexec.execSelect(); + for (; results.hasNext();) { + QuerySolution soln = results.nextSolution(); + assertTrue(soln.contains("c")); + assertTrue(soln.contains("x")); + assertEquals(3, soln.get("c").asLiteral().getInt()); + } + + builder.addVar("min(?o)", "?min").addVar("max(?o)", "?max"); + + qexec = QueryExecutionFactory.create(builder.build(), m); + + results = qexec.execSelect(); + for (; results.hasNext();) { + QuerySolution soln = results.nextSolution(); + assertTrue(soln.contains("c")); + assertTrue(soln.contains("x")); + assertTrue(soln.contains("?min")); + assertEquals(3, soln.get("c").asLiteral().getInt()); + assertEquals(1, soln.get("min").asLiteral().getInt()); + assertEquals(5, soln.get("max").asLiteral().getInt()); + } + } }
