Rob Vesse created JENA-1275: ------------------------------- Summary: TransformScopeRename does the wrong thing with FILTER NOT EXISTS Key: JENA-1275 URL: https://issues.apache.org/jira/browse/JENA-1275 Project: Apache Jena Issue Type: Bug Components: ARQ Affects Versions: Jena 3.1.1 Reporter: Rob Vesse
I have produced the following minimal query from an originally much larger query. When the optimise is applied to this it incorrectly double renames the variables inside of the {{FILTER NOT EXISTS}} clause leading to incorrect algebra. Query: {noformat} SELECT ?triangles ?openTriplets { { #subQ2: calculate #open-triplets SELECT (COUNT(?x) as ?openTriplets) WHERE { ?x ?a ?y . ?y ?b ?z . FILTER NOT EXISTS {?z ?c ?x} } } } {noformat} Output: {noformat} (project (?triangles ?openTriplets) (project (?openTriplets) (extend ((?openTriplets ?/.0)) (group () ((?/.0 (count ?/x))) (filter (notexists (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?//z ?//c ?//x))) (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?/x ?/a ?/y) (quad <urn:x-arq:DefaultGraphNode> ?/y ?/b ?/z) )))))) {noformat} Note that we apply the quad transformation prior to applying the optimiser. Strangely enough I cannot reproduce the problem using pure Jena command line tools i.e. {{qparse}} although I note from the code that it applies quad transformation after applying optimisation. This suggests that it is a bug in how TransformScopeRename applies to quad form algebra. I can reproduce it with a unit test like so: {noformat} @Test public void filter_not_exists_scoping_03() { //@formatter:off Op orig = SSE.parseOp(StrUtils.strjoinNL("(project (?triangles ?openTriplets)", " (project (?openTriplets)", " (extend ((?openTriplets ?.0))", " (group () ((?.0 (count ?x)))", " (filter (notexists", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?z ?c ?x)))", " (quadpattern", " (quad <urn:x-arq:DefaultGraphNode> ?x ?a ?y)", " (quad <urn:x-arq:DefaultGraphNode> ?y ?b ?z)", " ))))))")); Op expected = SSE.parseOp(StrUtils.strjoinNL("(project (?triangles ?openTriplets)", " (project (?openTriplets)", " (extend ((?openTriplets ?/.0))", " (group () ((?/.0 (count ?/x)))", " (filter (notexists", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?/z ?/c ?/x)))", " (quadpattern", " (quad <urn:x-arq:DefaultGraphNode> ?/x ?/a ?/y)", " (quad <urn:x-arq:DefaultGraphNode> ?/y ?/b ?/z)", " ))))))")); //@formatter:on Op transformed = TransformScopeRename.transform(orig); Assert.assertEquals(transformed, expected); } @Test public void filter_not_exists_scoping_04() { //@formatter:off Op orig = SSE.parseOp(StrUtils.strjoinNL( " (project (?openTriplets)", " (extend ((?openTriplets ?.0))", " (group () ((?.0 (count ?x)))", " (filter (notexists", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?z ?c ?x)))", " (quadpattern", " (quad <urn:x-arq:DefaultGraphNode> ?x ?a ?y)", " (quad <urn:x-arq:DefaultGraphNode> ?y ?b ?z)", " )))))")); Op expected = SSE.parseOp(StrUtils.strjoinNL( " (project (?openTriplets)", " (extend ((?openTriplets ?.0))", " (group () ((?.0 (count ?x)))", " (filter (notexists", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?z ?c ?x)))", " (quadpattern", " (quad <urn:x-arq:DefaultGraphNode> ?x ?a ?y)", " (quad <urn:x-arq:DefaultGraphNode> ?y ?b ?z)", " )))))")); //@formatter:on Op transformed = TransformScopeRename.transform(orig); Assert.assertEquals(transformed, expected); } {noformat} The first test fails while the second passes. This implies that you need 2 levels of projection to hit the bug. -- This message was sent by Atlassian JIRA (v6.3.4#6332)