mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-09 09:11:00 +08:00
Distilled from #1245 by Andrew Hundt (upstream b835b5e8), re-derived on
main's cypher.c rather than cherry-picked -- the file has moved ~9k lines
since the branch point.
The WHERE clause runs twice: once early, on seed rows where only the
first alias is bound, to prune; and once late, when every alias is bound,
to decide. The early pass used the same two-valued evaluator as the late
one. That evaluator answers "true" for a comparison on an alias it cannot
see -- the permissive default that makes the late pass work -- but NOT and
XOR invert whatever they are given, so
MATCH (a)-[:CALLS]->(b) WHERE NOT b.name CONTAINS "x"
evaluated NOT(true) on every seed and pruned every row. Zero results, no
error, for a query that is correct.
The early pass now uses a three-valued evaluator. A condition on an alias
that is not yet bound is UNKNOWN; NOT of UNKNOWN stays UNKNOWN; AND and OR
short-circuit only on a definite operand; XOR with any UNKNOWN operand is
UNKNOWN. Only a definite FALSE prunes. The late pass is unchanged and
still gives the final two-valued answer, so nothing that was correct
before changes.
Three deliberate differences from the upstream diff:
- the unbound-alias rule lives in one leaf, eval_condition_partial, so
the expression-tree path and main's legacy flat AND/OR path cannot
drift apart;
- that leaf guards c->variable == NULL. On main a condition whose left
side is a function of literals, coalesce(0, 1) >= 2, carries no
variable at all; the upstream version would have passed NULL to
strcmp;
- the flat path keeps main's rule that an empty condition list is true.
RED before the fix, all four with row_count == 0, expected 1:
cypher_exec_where_not_on_relationship_target,
cypher_exec_where_mixed_alias_and, ..._or, ..._xor. GREEN after: cypher
208 passed; cypher + mcp 526 passed, 4 skipped (the Windows-only skips).
eval_expr_partial recurses and is added to CBM_RECURSION_WHITELIST.
Co-authored-by: Andrew Hundt <ATHundt@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>