#3996 fix(cypher): CALL...YIELD preserves variables carried in from WITH#4009
#3996 fix(cypher): CALL...YIELD preserves variables carried in from WITH#4009
Conversation
Variables bound by a preceding WITH or MATCH clause were silently nulled out after a CALL...YIELD. The root cause was that CallStep collected procedure result iterators into a flat list with no association to the originating input row, so outer-scope variables were never merged into the yielded results. Fix: track each (inputRow, resultIterator) pair and merge inputRow properties into every yielded result via the existing mergeWithInputRow helper, restoring standard Cypher semantics across db.labels(), db.relationshipTypes(), db.propertyKeys(), and any registered procedure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Coverage variation | ✅ -7.85% coverage variation |
| Diff coverage | ✅ 86.67% diff coverage |
Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (983da3f) 120063 87787 73.12% Head commit (5851530) 151308 (+31245) 98751 (+10964) 65.26% (-7.85%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>
Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#4009) 15 13 86.67% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Code Review
This pull request addresses an issue where variables from preceding clauses were lost after a CALL ... YIELD statement by tracking and merging the original input row with procedure results. A comprehensive regression test suite has been added to verify this behavior across various database procedures. The review feedback suggests avoiding redundant merging in optional calls to prevent potential variable shadowing and recommends a performance optimization for the allPairs list initialization by setting an initial capacity.
… allPairs - OPTIONAL CALL with null result: use new ResultInternal() instead of pre-merging inputRow, avoiding redundant copy and preventing YIELD from seeing outer-scope variables under same-name collision - pre-size allPairs list with nRecords (capped at 1M) to avoid unnecessary ArrayList resizes during batch collection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4009 +/- ##
==========================================
+ Coverage 64.20% 64.23% +0.03%
==========================================
Files 1597 1597
Lines 120063 120069 +6
Branches 25556 25557 +1
==========================================
+ Hits 77083 77125 +42
+ Misses 32306 32276 -30
+ Partials 10674 10668 -6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
CALL db.labels() YIELD label(and all other procedures) were silently dropping variables bound by a precedingWITHorMATCHclause -xreturnednullon every row instead of its bound value.CallStep.executeChainedCall()collected procedure result iterators into a flatList<Iterator<?>>with no link back to the originating input row, so outer-scope variables were never merged into the yielded results.List<Map.Entry<Result, Iterator<?>>>pairs; the lazy iterator now trackscurrentInputRowand calls the existingmergeWithInputRow()helper for every yielded result, restoring standard Cypher semantics.Test plan
CypherCallYieldWithVariablesTest- 4 new regression tests coveringdb.labels(),db.relationshipTypes(),db.propertyKeys(), and aggregatedcount(*)carried throughWITHOpenCypherUnionCallProfileTest- existing CALL tests still passFixes #3996
🤖 Generated with Claude Code