Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c414714

Browse files
alvherrepull[bot]
authored andcommitted
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 <borz_off@cs.msu.su> Discussion: https://postgr.es/m/17579-82482cd7b267b862@postgresql.org
1 parent dcdef3d commit c414714

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

src/backend/commands/copy.c

Lines changed: 6 additions & 0 deletions
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

Lines changed: 7 additions & 0 deletions
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

Lines changed: 14 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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)