You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2015/07/14 18:21:50 UTC
[2/2] jena git commit: Follow-on from JENA-989: more cases of
producing a simpler query.
Follow-on from JENA-989: more cases of producing a simpler query.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/a31c7d27
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/a31c7d27
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/a31c7d27
Branch: refs/heads/master
Commit: a31c7d2718b85779d38c00abc74f8ab573dce41b
Parents: b43a3f2
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Jul 14 17:21:37 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Jul 14 17:21:37 2015 +0100
----------------------------------------------------------------------
.../apache/jena/sparql/algebra/OpAsQuery.java | 89 ++++++++++++--------
.../jena/sparql/algebra/TestOpAsQuery.java | 53 ++++++++++--
2 files changed, 104 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/a31c7d27/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
index 19e56da..a6e339c 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/OpAsQuery.java
@@ -450,30 +450,10 @@ public class OpAsQuery {
g = currentGroup() ;
}
- ElementPathBlock currentPathBlock = null ;
for ( Op op : opSequence.getElements() ) {
Element e = asElement(op) ;
- // -- Combining code.
- if ( e instanceof ElementPathBlock ) {
- if ( currentPathBlock != null ) {
- // Use last ElementPathBlock
- ElementPathBlock newPathBlock = (ElementPathBlock)e ;
- currentPathBlock.getPattern().addAll(newPathBlock.getPattern());
- // Don't add to the ElementGroup.
- continue ;
- } else {
- // Start an ElementPathBlock
- currentPathBlock = (ElementPathBlock)e ;
- // fall through to add the element.
- }
- } else {
- // Current element not a ElementPathBlock
- currentPathBlock = null ;
- }
- // -- End combining code
- g.addElement(e) ;
+ insertIntoGroup(g, e) ;
}
-
if ( nestGroup )
endSubGroup() ;
@@ -558,7 +538,7 @@ public class OpAsQuery {
ElementGroup eRightGroup = asElementGroup(opJoin.getRight()) ;
Element eRight = eRightGroup ;
// Very special case. If the RHS is not something that risks
- // reparsing into a copmbined element of a group, strip the group-of-one.
+ // reparsing into a combined element of a group, strip the group-of-one.
// See also ElementTransformCleanGroupsOfOne
if ( eRightGroup.size() == 1 ) {
// This always was a {} around it but it's unnecessary in a group of one.
@@ -567,8 +547,8 @@ public class OpAsQuery {
}
ElementGroup g = currentGroup() ;
- g.addElement(eLeft) ;
- g.addElement(eRight) ;
+ insertIntoGroup(g, eLeft) ;
+ insertIntoGroup(g, eRight) ;
return ;
}
@@ -747,18 +727,18 @@ public class OpAsQuery {
@Override
public void visit(OpAssign opAssign) {
Element e = asElement(opAssign.getSubOp()) ;
- if ( currentGroup() != e )
- currentGroup().addElement(e) ;
+ // If (assign ... (table unit)), and first in group, don't add the empty group.
+ insertIntoGroup(currentGroup(), e) ;
processAssigns(Arrays.asList(opAssign), (var,expr)->{
currentGroup().addElement(new ElementAssign(var,expr)) ;
}) ;
}
-
+
@Override
public void visit(OpExtend opExtend) {
Element e = asElement(opExtend.getSubOp()) ;
- if ( currentGroup() != e )
- currentGroup().addElement(e) ;
+ // If (extend ... (table unit)), and first in group, don't add the empty group.
+ insertIntoGroup(currentGroup(), e) ;
processExtends(Arrays.asList(opExtend), (var,expr)->{
currentGroup().addElement(new ElementBind(var,expr)) ;
}) ;
@@ -819,12 +799,55 @@ public class OpAsQuery {
throw new ARQNotImplemented("OpTopN") ;
}
+ /** Insert into a group, skip initial empty subgroups; recombining ElementPathBlock */
+ private static void insertIntoGroup(ElementGroup eg, Element e) {
+ // Skip initial empty subgroup.
+ if ( emptyGroup(e) && eg.isEmpty() )
+ return ;
+
+ // Empty group.
+ if ( eg.isEmpty() ) {
+ eg.addElement(e);
+ return ;
+ }
+
+ Element eltTop = eg.getLast() ;
+ if ( ! ( eltTop instanceof ElementPathBlock ) ) {
+ // Not working on a ElementPathBlock - no need to group-of-one
+ // when inserting ElementPathBlock.
+ e = unwrapGroupOfOnePathBlock(e) ;
+ eg.addElement(e);
+ return ;
+ }
+ if ( ! ( e instanceof ElementPathBlock ) ) {
+ eg.addElement(e);
+ return ;
+ }
+ // Combine.
+ ElementPathBlock currentPathBlock = (ElementPathBlock)eltTop ;
+ ElementPathBlock newPathBlock = (ElementPathBlock)e ;
+ currentPathBlock.getPattern().addAll(newPathBlock.getPattern());
+ }
+
+ private static Element unwrapGroupOfOnePathBlock(Element e) {
+ Element e2 = getElementOfGroupOfOne(e) ;
+ if ( e2 != null )
+ return e2 ;
+ return e ;
+ }
+
+ private static Element getElementOfGroupOfOne(Element e) {
+ if ( e instanceof ElementGroup ) {
+ ElementGroup eg = (ElementGroup)e ;
+ if ( eg.size() == 1 )
+ return eg.get(0) ;
+ }
+ return null ;
+ }
+
private Element lastElement() {
ElementGroup g = currentGroup ;
- if ( g == null || g.size() == 0 )
- return null ;
- int len = g.size() ;
- return g.get(len - 1) ;
+ return g.getLast() ;
}
private void startSubGroup() {
http://git-wip-us.apache.org/repos/asf/jena/blob/a31c7d27/jena-arq/src/test/java/org/apache/jena/sparql/algebra/TestOpAsQuery.java
----------------------------------------------------------------------
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 6e37c2d..ab8666f 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
@@ -30,6 +30,7 @@ import org.apache.jena.query.QueryFactory ;
import org.apache.jena.query.Syntax ;
import org.apache.jena.sparql.algebra.Algebra ;
import org.apache.jena.sparql.algebra.Op ;
+import org.apache.jena.sparql.sse.SSE ;
import org.junit.Assert ;
import org.junit.Test ;
@@ -128,10 +129,7 @@ public class TestOpAsQuery {
{ test_roundTripQuery("SELECT ?s { ?s ?p ?o { SELECT (count(*) as ?cp) { ?s ?p ?o } }}") ; }
@Test public void testSubQuery_03()
- //{ test_roundTripQuery("SELECT ?s { { SELECT (count(*) as ?cp) { ?s ?p ?o } } ?s ?p ?o }") ; }
- // The trailing ?s ?p ?o gets a {} round it.
- { test_equivalentQuery("SELECT ?s { { SELECT (count(*) as ?cp) { ?s ?p ?o } } ?s ?p ?o }",
- "SELECT ?s { { SELECT (count(*) as ?cp) { ?s ?p ?o } } { ?s ?p ?o } }") ; }
+ { test_roundTripQuery("SELECT ?s { { SELECT (count(*) as ?cp) { ?s ?p ?o } } ?s ?p ?o }") ; }
@Test public void testSubQuery_04()
{ test_roundTripQuery("SELECT * WHERE { ?s ?p ?o . BIND(?o AS ?x) }") ; }
@@ -387,10 +385,46 @@ public class TestOpAsQuery {
test_roundTripAlegbra(query) ;
}
+ @Test
+ public void testValues1() {
+ String query = "SELECT * { VALUES ?x {1 2} ?s ?p ?x }" ;
+ test_roundTripQuery(query) ;
+ }
+
+ @Test
+ public void testValues2() {
+ String query = "SELECT * { ?s ?p ?x VALUES ?x {1 2} }" ;
+ test_roundTripQuery(query) ;
+ }
+
+ // Algebra to query : optimization cases OpAsQuery can handle.
+
+ @Test
+ public void testAlgebra01() {
+ String opStr = "(sequence (bgp (?s1 ?p1 ?o1)) (bgp (?s2 ?p2 ?o2)) )" ;
+ String query = "SELECT * { ?s1 ?p1 ?o1. ?s2 ?p2 ?o2}" ;
+ test_AlgebraToQuery(opStr, query);
+ }
+
+ @Test
+ public void testAlgebra02() {
+ String opStr = "(sequence (bgp (?s1 ?p1 ?o1)) (path ?x (path* :p) ?z) )" ;
+ String query = "PREFIX : <http://example/> SELECT * { ?s1 ?p1 ?o1. ?x :p* ?z}" ;
+ test_AlgebraToQuery(opStr, query);
+ }
+
+ @Test
+ public void testAlgebra03() {
+ String opStr = "(sequence (path ?x (path* :p) ?z) (bgp (?s1 ?p1 ?o1)) )" ;
+ String query = "PREFIX : <http://example/> SELECT * { ?x :p* ?z . ?s1 ?p1 ?o1. }" ;
+ test_AlgebraToQuery(opStr, query);
+ }
+
// There 3 classes of transformations: there are 3 main test operations.
// test_roundTripQuery: The same query is recovered from OpAsQuery
// test_roundTripAlegbra: Different queries with the same alegra forms
// test_equivalentQuery: Different equivalent queries - same answers, different algebra.
+ // test_algebraToQuery: algebra to query (e.g. optimization shapes)
//
// test_roundTripQuery is test_equivalentQuery with same input and expected.
// + quad variants.
@@ -432,6 +466,15 @@ public class TestOpAsQuery {
Op a2 = Algebra.compile(r[1]);
Assert.assertEquals(a1, a2);
}
+
+ // algebra->OpAsQuery->query
+ public static void test_AlgebraToQuery(String input, String expected) {
+ Op op = SSE.parseOp(input) ;
+ Query orig = QueryFactory.create(expected, Syntax.syntaxSPARQL_11);
+ stripNamespacesAndBase(orig) ;
+ Query got = OpAsQuery.asQuery(op);
+ Assert.assertEquals(orig, got) ;
+ }
// query->algebra->OpAsQuery->query
private static Query[] roundTripQuery(String query) {
@@ -442,7 +485,7 @@ public class TestOpAsQuery {
return r;
}
- // query->algebra/quads->OpAsQuery->query
+ // query->algebra/quads->OpAsQuery->query
private static Query[] roundTripQueryQuad(String query) {
Query orig = QueryFactory.create(query, Syntax.syntaxSPARQL_11);
Op toReconstruct = Algebra.compile(orig);