Skip to content

Commit 92af914

Browse files
committed
Reject MERGE in CTEs and COPY
The grammar added for MERGE inadvertently made it accepted syntax in places that were not prepared to deal with it -- namely COPY and inside CTEs, but invoking these things with MERGE currently causes assertion failures or weird misbehavior in non-assertion builds. Protect those places by checking for it explicitly until somebody decides to implement it. Reported-by: Alexey Borzov <[email protected]> Discussion: https://postgr.es/m/[email protected]
1 parent e7a552f commit 92af914

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

src/backend/commands/copy.c

+6
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
273273
{
274274
Assert(stmt->query);
275275

276+
/* MERGE is allowed by parser, but unimplemented. Reject for now */
277+
if (IsA(stmt->query, MergeStmt))
278+
ereport(ERROR,
279+
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
280+
errmsg("MERGE not supported in COPY"));
281+
276282
query = makeNode(RawStmt);
277283
query->stmt = stmt->query;
278284
query->stmt_location = stmt_location;

src/backend/parser/parse_cte.c

+7
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
126126
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
127127
ListCell *rest;
128128

129+
/* MERGE is allowed by parser, but unimplemented. Reject for now */
130+
if (IsA(cte->ctequery, MergeStmt))
131+
ereport(ERROR,
132+
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
133+
errmsg("MERGE not supported in WITH query"),
134+
parser_errposition(pstate, cte->location));
135+
129136
for_each_cell(rest, withClause->ctes, lnext(withClause->ctes, lc))
130137
{
131138
CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest);

src/test/regress/expected/merge.out

+14
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ ON tid = tid
123123
WHEN MATCHED THEN DO NOTHING;
124124
ERROR: name "target" specified more than once
125125
DETAIL: The name is used both as MERGE target table and data source.
126+
-- used in a CTE
127+
WITH foo AS (
128+
MERGE INTO target USING source ON (true)
129+
WHEN MATCHED THEN DELETE
130+
) SELECT * FROM foo;
131+
ERROR: MERGE not supported in WITH query
132+
LINE 1: WITH foo AS (
133+
^
134+
-- used in COPY
135+
COPY (
136+
MERGE INTO target USING source ON (true)
137+
WHEN MATCHED THEN DELETE
138+
) TO stdout;
139+
ERROR: MERGE not supported in COPY
126140
-- unsupported relation types
127141
-- view
128142
CREATE VIEW tv AS SELECT * FROM target;

src/test/regress/sql/merge.sql

+10
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ MERGE INTO target
8888
USING target
8989
ON tid = tid
9090
WHEN MATCHED THEN DO NOTHING;
91+
-- used in a CTE
92+
WITH foo AS (
93+
MERGE INTO target USING source ON (true)
94+
WHEN MATCHED THEN DELETE
95+
) SELECT * FROM foo;
96+
-- used in COPY
97+
COPY (
98+
MERGE INTO target USING source ON (true)
99+
WHEN MATCHED THEN DELETE
100+
) TO stdout;
91101

92102
-- unsupported relation types
93103
-- view

0 commit comments

Comments
 (0)