ingraph icon indicating copy to clipboard operation
ingraph copied to clipboard

Incorrect query plans for queries starting with WITH

Open szarnyasg opened this issue 6 years ago • 3 comments

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))

szarnyasg avatar Mar 05 '18 21:03 szarnyasg

Test case in 81d962e.

szarnyasg avatar Mar 05 '18 21:03 szarnyasg

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))

jmarton avatar Aug 12 '18 13:08 jmarton

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))

jmarton avatar Aug 12 '18 15:08 jmarton