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)