summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-08-12 12:05:50 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-08-12 12:05:50 +0200
commit455d254d22665eb7af3b714435f3fecc63696cc7 (patch)
tree3fed7037832968b7a77391721e86f1d1622778f1
parente1878cf94134429bf951b41ed523363c2fa2d6b4 (diff)
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
-rw-r--r--src/backend/commands/copy.c6
-rw-r--r--src/backend/parser/parse_cte.c7
-rw-r--r--src/test/regress/expected/merge.out14
-rw-r--r--src/test/regress/sql/merge.sql10
4 files changed, 37 insertions, 0 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index e2870e3c11c..2e90563333e 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -273,6 +273,12 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
{
Assert(stmt->query);
+ /* MERGE is allowed by parser, but unimplemented. Reject for now */
+ if (IsA(stmt->query, MergeStmt))
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MERGE not supported in COPY"));
+
query = makeNode(RawStmt);
query->stmt = stmt->query;
query->stmt_location = stmt_location;
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index efb4af706e1..8fc86586085 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -126,6 +126,13 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
ListCell *rest;
+ /* MERGE is allowed by parser, but unimplemented. Reject for now */
+ if (IsA(cte->ctequery, MergeStmt))
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("MERGE not supported in WITH query"),
+ parser_errposition(pstate, cte->location));
+
for_each_cell(rest, withClause->ctes, lnext(withClause->ctes, lc))
{
CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest);
diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out
index af670e28e7f..729ae2eb065 100644
--- a/src/test/regress/expected/merge.out
+++ b/src/test/regress/expected/merge.out
@@ -123,6 +123,20 @@ ON tid = tid
WHEN MATCHED THEN DO NOTHING;
ERROR: name "target" specified more than once
DETAIL: The name is used both as MERGE target table and data source.
+-- used in a CTE
+WITH foo AS (
+ MERGE INTO target USING source ON (true)
+ WHEN MATCHED THEN DELETE
+) SELECT * FROM foo;
+ERROR: MERGE not supported in WITH query
+LINE 1: WITH foo AS (
+ ^
+-- used in COPY
+COPY (
+ MERGE INTO target USING source ON (true)
+ WHEN MATCHED THEN DELETE
+) TO stdout;
+ERROR: MERGE not supported in COPY
-- unsupported relation types
-- view
CREATE VIEW tv AS SELECT * FROM target;
diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql
index afeb212f3c8..e0c450736bd 100644
--- a/src/test/regress/sql/merge.sql
+++ b/src/test/regress/sql/merge.sql
@@ -88,6 +88,16 @@ MERGE INTO target
USING target
ON tid = tid
WHEN MATCHED THEN DO NOTHING;
+-- used in a CTE
+WITH foo AS (
+ MERGE INTO target USING source ON (true)
+ WHEN MATCHED THEN DELETE
+) SELECT * FROM foo;
+-- used in COPY
+COPY (
+ MERGE INTO target USING source ON (true)
+ WHEN MATCHED THEN DELETE
+) TO stdout;
-- unsupported relation types
-- view