ingraph
ingraph copied to clipboard
Incorrect query plans for queries starting with WITH
Queries starting with WITH
produce incorrect plans: the selection relies on the x
attribute which is not present. The issue is also present for queries starting with UNWIND
.
Query:
------
WITH 1 AS x
MATCH (some:Thing {prop: x})
RETURN some.prop
-----------------------------------------------------------------------------
QPlan:
------
'Production
+- 'Projection [ret(p(prop, v(some, {}, false, (some#0)), (some$prop#0)), None, (some$prop#0))]
+- 'Join
:- !Projection [ret(1, (x), (x#0))]
: +- Dual
+- 'AllDifferent
+- 'Selection (p(prop, v(some, {}, false, (some#0)), (some$prop#0)) = expr(1, x, (x#0)))
+- 'GetVertices v(some, {Thing}, (prop,'x), false, (some#0))
Test case in 81d962e.
An even more tricky query is given to show that it is not a viable solution to raise the selection above the join operator used to combine query parts, because for outer joins, this could kill the outer nature of the join.
Query:
------
WITH 1 AS x
MATCH (some:Thing)
OPTIONAL MATCH (some)-->(other: Thing {prop: x})
RETURN some, other.prop
-----------------------------------------------------------------------------
GPlan:
------
'Production
+- 'Projection [ret(v(some, {}, false, (some#0)), None, (some#0)), ret(p(prop, v(other, {}, false, (other#0)), (other$prop#0)), None, (other$prop#0))]
+- 'LeftOuterJoin
:- 'Join
: :- !Projection [ret(1, (x), (x#0))]
: : +- Dual
: +- 'AllDifferent
: +- 'GetVertices v(some, {Thing}, false, (some#0))
+- 'AllDifferent [e(_e0, {}, true, (_e0#0))]
+- 'Selection (p(prop, v(other, {}, false, (other#0)), (other$prop#0)) = expr(1, x, (x#0)))
+- 'Expand v(some, {}, false, (some#0)), v(other, {Thing}, (prop,'x), false, (other#0)), e(_e0, {}, true, (_e0#0)), Out
+- 'GetVertices v(some, {}, false, (some#0))
Note: this is not even specific to queries starting with WITH, but seems to be characterized as problem with compilation of correlated query parts where correlation involves other than graph objects (e.g. properties, constants).
E.g. for the example graph on console.neo4j.com, a query and its GPlan can be seen below. Note the use of crewName#0
in the selection, while it is not available there.
Query:
------
MATCH (n:Crew {name: 'Neo'})
WITH n.name AS crewName
MATCH (p1:Crew)
OPTIONAL MATCH (p1)--(p2:Crew {name: crewName})
RETURN p1, p2
-------------------------------------------------
GPlan:
------
'Production
+- 'Projection [ret(v(p1, {}, false, (p1#0)), None, (p1#0)), ret(v(p2, {}, false, (p2#0)), None, (p2#0))]
+- 'LeftOuterJoin
:- 'Join
: :- 'Projection [ret(p(name, v(n, {}, false, (n#0)), (n$name#0)), (crewName), (crewName#0))]
: : +- 'AllDifferent
: : +- 'Selection (p(name, v(n, {}, false, (n#0)), (n$name#0)) = Neo)
: : +- 'GetVertices v(n, {Crew}, (name,Neo), false, (n#0))
: +- 'AllDifferent
: +- 'GetVertices v(p1, {Crew}, false, (p1#0))
+- 'AllDifferent [e(_e0, {}, true, (_e0#0))]
+- 'Selection (p(name, v(p2, {}, false, (p2#0)), (p2$name#0)) = p(name, v(n, {}, false, (n#0)), (crewName#0)))
+- 'Expand v(p1, {}, false, (p1#0)), v(p2, {Crew}, (name,'crewName), false, (p2#0)), e(_e0, {}, true, (_e0#0)), Both
+- 'GetVertices v(p1, {}, false, (p1#0))