ftsrg / ingraph

Incremental view maintenance for openCypher graph queries.
http://docs.inf.mit.bme.hu/ingraph/
Eclipse Public License 1.0
48 stars 10 forks source link

Incorrect query plans for queries starting with WITH #335

Open szarnyasg opened 6 years ago

szarnyasg commented 6 years ago

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 commented 6 years ago

Test case in 81d962e.

jmarton commented 6 years ago

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 commented 6 years ago

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