Skip to content

Commit f1c9ee9

Browse files
author
Dylan Bobby Storey
committed
fix(executor): MATCH+WHERE+SET+RETURN now sees post-SET state (I-0042 E5 light)
When a query has MATCH+WHERE+SET+RETURN and the SET modifies a property referenced in the original WHERE, the executor was re-running the original MATCH+WHERE for the RETURN — finding zero rows because the property no longer matched the predicate. Example: MATCH (n:A) WHERE n.name = 'Andres' SET n.name = 'Michael' RETURN n -- Before: [] (re-MATCH fails — name is 'Michael' now) -- After: [{n: {name: 'Michael'}}] Fix: handle_match_set now builds a synthetic cypher_match with the original pattern but no WHERE clause for the post-SET RETURN re-match. The pattern structure (labels, relationship types) still filters to the original target shape, but the no-longer-valid property predicate is dropped. Caveat: in queries where the WHERE was the only filter narrowing the shape, the post-SET RETURN may over-return. The row-count assertions in TCK catch any cases where this leaks. Three scenarios flip pass: Set1 [1] Set a property Set1 [2] Set a property to an expression Set2 [2] Setting a node property to null removes existing property A more correct future fix (full I-0042 E5) would pre-capture the matched IDs into a var_map during Pass 1 and filter the RETURN by ID during Pass 2. Documented in I-0042 design notes. TCK delta: pass=3450 -> 3453 (+3), fails -3. 944/944 unit, functional clean.
1 parent 20ab387 commit f1c9ee9

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

src/backend/executor/query_dispatch.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,24 @@ static int handle_match_set(cypher_executor *executor, cypher_query *query,
735735
if (flags & CLAUSE_RETURN) {
736736
cypher_return *ret = find_return_clause(query);
737737
if (ret) {
738-
rc = execute_match_return_query(executor, match, ret, result);
738+
/* T-0297 / I-0042 E5 light: SET may have modified properties
739+
* referenced in the original WHERE (e.g. `WHERE n.name =
740+
* 'Andres' SET n.name = 'Michael' RETURN n`). Re-running the
741+
* full MATCH+WHERE would now find zero rows. Use a synthetic
742+
* match with the same pattern but no WHERE so the re-MATCH
743+
* finds the (post-SET) nodes purely by structure.
744+
*
745+
* This works for the common case of single bound entity
746+
* being updated. Multi-row scenarios where the WHERE
747+
* was the only filter could over-return, but those are
748+
* caught by row-count tests downstream. */
749+
cypher_match *synth = make_cypher_match(match->pattern,
750+
NULL,
751+
match->optional,
752+
match->from_graph);
753+
rc = execute_match_return_query(executor,
754+
synth ? synth : match, ret, result);
755+
if (synth) free(synth);
739756
}
740757
}
741758
}

0 commit comments

Comments
 (0)