Add MERGE ON CREATE SET / ON MATCH SET support (#1619)#2347
Open
gregfelice wants to merge 1 commit intoapache:masterfrom
Open
Add MERGE ON CREATE SET / ON MATCH SET support (#1619)#2347gregfelice wants to merge 1 commit intoapache:masterfrom
gregfelice wants to merge 1 commit intoapache:masterfrom
Conversation
Implements the openCypher-standard ON CREATE SET and ON MATCH SET
clauses for the MERGE statement. This allows conditional property
updates depending on whether MERGE created a new path or matched
an existing one:
MERGE (n:Person {name: 'Alice'})
ON CREATE SET n.created = timestamp()
ON MATCH SET n.updated = timestamp()
Implementation spans parser, planner, and executor:
- Grammar: new merge_actions_opt/merge_actions/merge_action rules
in cypher_gram.y, with ON keyword added to cypher_kwlist.h
- Nodes: on_match/on_create lists on cypher_merge, corresponding
on_match_set_info/on_create_set_info on cypher_merge_information,
and prop_expr on cypher_update_item (all serialized through
copy/out/read funcs)
- Transform: cypher_clause.c transforms ON SET items and stores
prop_expr for direct expression evaluation
- Executor: cypher_set.c extracts apply_update_list() from
process_update_list(); cypher_merge.c calls it at all merge
decision points (simple merge, terminal, non-terminal with
eager buffering, and first-clause-with-followers paths)
Key design choice: prop_expr stores the Expr* directly in
cypher_update_item rather than using prop_position into the scan
tuple. The planner strips target list entries for SET expressions
that CustomScan doesn't need, making prop_position references
dangling. By storing the expression directly (only for MERGE ON
SET items), we evaluate it with ExecInitExpr/ExecEvalExpr
independent of the scan tuple layout.
Includes regression tests covering: basic ON CREATE SET, basic
ON MATCH SET, combined ON CREATE + ON MATCH, multiple SET items,
expression evaluation, interaction with WITH clause, and edge
property updates.
All 31 regression tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the openCypher-standard
ON CREATE SETandON MATCH SETclauses for the MERGE statement, resolving #1619. This allows conditional property updates depending on whether MERGE created a new path or matched an existing one:Design
The implementation spans parser, planner, and executor:
Parser — New grammar rules (
merge_actions_opt,merge_actions,merge_action) incypher_gram.y. TheONkeyword is added tocypher_kwlist.h.Nodes —
on_match/on_createlists oncypher_merge, correspondingon_match_set_info/on_create_set_infooncypher_merge_information, andprop_exproncypher_update_item. All fields serialized through copy/out/read funcs.Transform —
cypher_clause.ctransforms ON SET items and storesprop_exprfor direct expression evaluation.Executor —
apply_update_list()is extracted fromprocess_update_list()incypher_set.cas reusable SET logic.cypher_merge.ccalls it at all merge decision points:Why prop_expr?
The PostgreSQL planner strips target list entries for SET expressions that the CustomScan doesn't reference. This makes
prop_positionreferences into the scan tuple dangling. The solution: store theExpr*directly incypher_update_item->prop_exprand evaluate it withExecInitExpr/ExecEvalExpr, independent of scan tuple layout. This is only done for MERGE ON SET items — regular SET continues to useprop_positionunchanged.Files changed (12)
src/include/parser/cypher_kwlist.hONkeywordsrc/backend/parser/cypher_gram.ysrc/include/nodes/cypher_nodes.hsrc/backend/nodes/cypher_copyfuncs.csrc/backend/nodes/cypher_outfuncs.csrc/backend/nodes/cypher_readfuncs.csrc/backend/parser/cypher_clause.csrc/include/executor/cypher_utils.happly_update_listdeclarationsrc/backend/executor/cypher_set.capply_update_list()fromprocess_update_list()src/backend/executor/cypher_merge.capply_update_listat all merge decision pointsregress/sql/cypher_merge.sqlregress/expected/cypher_merge.outTest plan
Closes #1619