Skip to content

feat(cypher): coalesce(var.prop, literal) in WHERE clauses#1034

Merged
DeusData merged 1 commit into
mainfrom
fix/874-cypher-coalesce
Jul 11, 2026
Merged

feat(cypher): coalesce(var.prop, literal) in WHERE clauses#1034
DeusData merged 1 commit into
mainfrom
fix/874-cypher-coalesce

Conversation

@DeusData

Copy link
Copy Markdown
Owner

Closes #874.

WHERE coalesce(f.transitive_loop_depth, 0) >= 2 — the reporter's exact null-safe audit filter — parsed with 'unexpected operator'. RETURN-side coalesce already existed; the WHERE leaf now supports it too.

Design: the condition leaf carries an optional coalesce_default literal; the operator/value tail is factored into a shared parse_condition_op, so the coalesce subject accepts the full operator set (comparisons, IS [NOT] NULL, IN) identically to a bare var.prop. Eval substitutes the default for missing/empty property values — real openCypher two-arg null-substitution semantics, not a rewrite trick.

Reproduce-first: the reporter's query is the test — RED (rc=-1) on the old parser; GREEN pins both directions (failing default excludes property-less nodes, passing default includes them).

Full suite 5,997/0, lint-ci clean.

@DeusData DeusData added this to the 0.9.1-rc milestone Jul 11, 2026
@DeusData
DeusData enabled auto-merge July 11, 2026 17:09
The WHERE parser rejected coalesce() outright ('unexpected operator'),
blocking null-safe numeric filters over optional graph properties —
the exact audit-query shape from the report:
  MATCH (f:Function) WHERE coalesce(f.transitive_loop_depth, 0) >= 2
RETURN-side coalesce already worked; only the WHERE leaf lacked it.

Implementation: the condition leaf gains a coalesce_default literal.
The operator/value tail of condition parsing is factored into a shared
parse_condition_op so both subjects (var[.prop] and
coalesce(var.prop, literal)) accept the full operator set (comparisons,
IS [NOT] NULL, IN). At eval time a missing/empty property value is
substituted with the default before the operator runs. Supported form
is coalesce(var.prop, literal) — matching openCypher's two-argument
null-substitution for this subset.

Reproduce-first: cypher_exec_where_coalesce_issue874 runs the
reporter's exact query — RED (rc=-1 parse error) on the old parser —
and pins both directions: a failing default excludes property-less
nodes, a passing default includes them.

Closes #874

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData merged commit e19a699 into main Jul 11, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

query_graph Cypher: coalesce() in WHERE rejected (unexpected operator)

1 participant