thatdot/quine

UNWIND regression in 1.2 release

jiminoc opened this issue · 4 comments

When trying to test the 1.2 JAR I was getting failures in previously working standing queries with UNWIND where I'm working with an expected map. When retested against the 1.1 open source JAR the queries were successfully accepted and working.

ERROR
MATCH (n) WHERE id(n) = $sqMatch.data.id WITH n.tags AS tags, n UNWIND keys(tags) AS key MATCH (m) WHERE id(m) = idFrom(n.cid, 'tag', key, n.tags[key]) CREATE (n)-[:tag]->(m) SET m.key = key, m.value = n.tags[key], m:tag NOT Registered OK for tagquery on http://10.10.10.10:8080: ["Type mismatch: expected Map, Node or Relationship but was Boolean, Float, Integer, Number, Point, String, Duration, Date, Time, LocalTime, LocalDateTime, DateTime, List<Boolean>, List<Float>, List<Integer>, List<Number>, List<Point>, List<String>, List<Duration>, List<Date>, List<Time>, List<LocalTime>, List<LocalDateTime> or List<DateTime>"]

Queries
standing_match_tags = """MATCH (n) WHERE exists(n.tags) RETURN id(n)""" standing_action_tags = ( """MATCH (n) WHERE id(n) = $sqMatch.data.id """ """WITH n.tags AS tags, n """ """UNWIND keys(tags) AS key """ """MATCH (m) WHERE id(m) = idFrom(n.foobar, 'tag', key, n.tags[key]) """ """CREATE (n)-[:tag]->(m) """ """SET m.key = key, m.value = n.tags[key], m:tag""" )

Reproduction using only ad-hoc queries:

Query 1:

MATCH (n) WHERE id(n) = idFrom(0) SET n = {
  tags: {
    foo: "bar",
    fizz: "buzz"
  }
}

Query 2:

MATCH (n) WHERE id(n) = idFrom(0)
UNWIND keys(n.tags) AS key RETURN key

On 1.1.0 this returns 2 rows for "key": "foo" and "fizz". On 1.2.0, it produces a type mismatch error like the one provided in the original ticket.

This seems tied to using a property specifically. Notably, Query 2 fails to compile in isolation (ie on an empty Quine instance) -- this implies the problem is in the cypher compiler

Additionally, both of the following work on 1.1.0 and 1.2.0:

UNWIND keys() of a map literal:
UNWIND keys({foo: "bar", fizz: "buzz"}) AS key RETURN key
UNWIND keys() of a node variable:
MATCH (n) WHERE id(n) = idFrom(0) UNWIND keys(n) AS key RETURN key

As a temporary workaround, this also works on 1.2.0: instead of passing n.tags to keys(), pass properties(n)["tags"]

MATCH (n) WHERE id(n) = $sqMatch.data.id
UNWIND keys(properties(n)["tags"]) AS key
MATCH (m) WHERE id(m) = idFrom(n.cid, 'tag', key, n.tags[key])
CREATE (n)-[:tag]->(m)
SET m.key = key, m.value = n.tags[key], m:tag

The root cause seems to be upstream of Quine, in openCypher: Other cypher interpreters using openCypher have the same problem:

image

We may be able to patch around this issue in our compilation pipeline with a bit more custom logic during function resolution; looking into that possibility now.

A more thorough workaround has been introduced in edecbcc and is scheduled to be included in the next release. A new set of casting cypher functions may be used to hint to the compiler what the expected type of a value is:
Here's an example of usage

| UNWIND keys(castOrThrow.map(n.tags)) AS key RETURN key

Closing this for now, as while we'd like to implement a more thorough solution to this issue, we believe this workaround will be an effective mitigation in the near term