Skip to content

feat: support MERGE ... WHEN NOT MATCHED BY TARGET / BY SOURCE (#2421) - #2453

Open
fudianchn wants to merge 1 commit into
JSQLParser:masterfrom
fudianchn:merge-not-matched-by-target-source
Open

feat: support MERGE ... WHEN NOT MATCHED BY TARGET / BY SOURCE (#2421)#2453
fudianchn wants to merge 1 commit into
JSQLParser:masterfrom
fudianchn:merge-not-matched-by-target-source

Conversation

@fudianchn

Copy link
Copy Markdown
Contributor

Problem

BigQuery and SQL Server allow the MERGE ... WHEN NOT MATCHED clause to be qualified with BY TARGET (default, allows INSERT) or BY SOURCE (allows UPDATE/DELETE). JSQLParser currently rejects it as an UnsupportedStatement (#2421):

MERGE INTO target_table AS tt
USING (SELECT key, field FROM source_table) AS st ON tt.key = st.key
WHEN NOT MATCHED BY TARGET THEN INSERT (key, field) VALUES (st.key, st.field)
WHEN NOT MATCHED BY SOURCE THEN DELETE;

The grammar's MergeWhenNotMatched had no BY branch and was hard-wired to INSERT.

Change

  • Grammar (JSqlParserCC.jjt): add an optional [BY TARGET|SOURCE] to WHEN NOT MATCHED, and let that branch produce INSERT, UPDATE, or DELETE (extracted MergeInsertClause helper so all three branches stay simple, mirroring MergeWhenMatched). Standard SQL WHEN [NOT] MATCHED (no BY) is unchanged.
  • Model: new MergeSide { TARGET, SOURCE } enum + a side field on MergeInsert/MergeUpdate/MergeDelete, rendered by both toString() and the MergeDeParser visitor.
  • TARGET/SOURCE are matched as identifiers (S_IDENTIFIER) rather than reserved keywords, so existing SQL that uses them as column/table names is unaffected.

Verification

  • New tests in MergeTest cover BY TARGET (INSERT) + BY SOURCE (DELETE), and BY SOURCE ... THEN UPDATE with an AND predicate — each with a round-trip assertSqlCanBeParsedAndDeparsed plus AST assertions on the side field.
  • Full suite: 4659 tests, 0 failures. checkstyle / pmd / license:check-file-header clean.
  • Backward compatible: existing WHEN MATCHED ... UPDATE/DELETE and WHEN NOT MATCHED ... INSERT tests keep passing (23 pre-existing Merge tests unaffected).

Fixes #2421.

BigQuery and SQL Server allow the MERGE NOT MATCHED clause to be
qualified with BY TARGET (allows INSERT) or BY SOURCE (allows
UPDATE/DELETE), e.g.:

    MERGE INTO t USING s ON ...
    WHEN NOT MATCHED BY TARGET THEN INSERT (...)
    WHEN NOT MATCHED BY SOURCE THEN DELETE

Previously JSQLParser rejected the BY TARGET/BY SOURCE qualifier as an
UnsupportedStatement (JSQLParser#2421).

Add an optional [BY TARGET|SOURCE] to the WHEN NOT MATCHED production,
allow INSERT/update/delete on that branch, and store the side on the
MergeInsert/MergeUpdate/MergeDelete operations via a new MergeSide enum.
Standard WHEN [NOT] MATCHED (no BY) keeps working unchanged.

TARGET/SOURCE are matched as identifiers (not reserved keywords), so
existing SQL using them as column/table names is unaffected.

Fixes JSQLParser#2421

Signed-off-by: 付典 <fudianchn@gmail.com>
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.

[BUG] BigQuery statement MERGE ... WHEN NOT MATCHED BY TARGET

1 participant