Skip to content

query_graph: UNWIND is parsed but silently ignored (README says supported / should error) #1192

Open

Description

@eazene

Summary

query_graph accepts UNWIND without error but never executes it — the clause is parsed and then ignored by the executor, so the rest of the query runs as if the UNWIND were absent. This contradicts the README, which both lists UNWIND as supported and states that unsupported syntax "fails with a clear unsupported … error." Instead the user gets a silently wrong result.

Reproduction (v0.9.0)

query_graph:
  UNWIND [1,2,3] AS x MATCH (f:Function) WHERE f.name = 'main' RETURN f.name

Expected (per README): either 3× row multiplication, or a clear "unsupported" error.
Actual: the UNWIND is ignored; the MATCH runs once and returns its rows with no error and no warning.

Location

Parser accepts UNWIND (src/cypher/cypher.c:1832-1866) but the executor loop (cypher.c:4635-4694) has no UNWIND handling, so x is never bound and no row expansion occurs.

Suggested fix

Either implement UNWIND (bind the list elements and cross-product with subsequent MATCH/RETURN), or — consistent with the documented contract — reject it with the same unsupported … error path used for other unimplemented clauses so it fails loudly instead of silently.

Related

A sibling correctness gap: comparisons against unbound OPTIONAL MATCH variables evaluate TRUE (~cypher.c:2611-2612), which is also a silent-wrong-answer path. Happy to file separately if preferred.

Activity

  1. added
    cypherCypher query language parser/executor bugs
    parsing/qualityGraph extraction bugs, false positives, missing edges
    on Jul 21, 2026
  2. added
    bugSomething isn't working
    ux/behaviorDisplay bugs, docs, adoption UX
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    on Jul 22, 2026
  3. added this to the 0.9.1-rc milestone on Jul 22, 2026
  4. DeusData commented on Jul 25, 2026

    @DeusData
    Owner

    Thank you for this — it is an unusually well-researched report, and both findings reproduce on current main (97ce23f).

    UNWIND is confirmed. The clause parses into q->unwind_expr / q->unwind_alias (src/cypher/cypher.c:1858-1865), and those two fields are thereafter only ever freed (cypher.c:2109-2110) — there is no read of either anywhere in the executor. So the parse succeeds, the alias never binds, and no row expansion happens: exactly the silent-wrong-answer path you describe.

    The documented contract is also exactly as you quote it — README.md:608 lists UNWIND among the supported clauses, while README.md:614 promises that anything outside the subset "fails with a clear unsupported … error rather than returning empty results." UNWIND currently falls into the gap between those two sentences, which is the worst of both options.

    The sibling finding is confirmed as well. cypher.c:2612-2614 reads if (!actual) { return true; } — an unresolvable condition value makes the predicate pass unconditionally, so a WHERE against an unbound OPTIONAL MATCH variable succeeds instead of behaving like a comparison against null. Please do file that separately; it is a distinct root cause with a different blast radius (it affects every OPTIONAL MATCH query, not just UNWIND), and it deserves its own tracking issue.

    Which way the UNWIND gap gets closed — implementing the row expansion, or rejecting the clause loudly so it matches the documented contract — is a deliberate design call rather than a triage one, so I am leaving that open here rather than pre-committing. Keeping it at priority/high either way: a silently wrong result is worse than a hard error.

    Thanks again for tracing this to the exact lines and for flagging the sibling case rather than bundling it.

  5. DeusData commented on Oct 19, 2026

    @DeusData
    Owner

    Thank you for the precise UNWIND report. The silent acceptance versus actual row expansion remains the correctness issue; I have no new verified outcome or implementation decision to add.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcypherCypher query language parser/executor bugsparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.ux/behaviorDisplay bugs, docs, adoption UX

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions