aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/createas.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2020-12-30 21:23:24 +0900
committerMichael Paquier <michael@paquier.xyz>2020-12-30 21:23:24 +0900
commite665769e6d1e84b6650f53ed297058fc11152f7f (patch)
tree82a4f55f692707741f6397cedeb8e02894ac69aa /src/backend/commands/createas.c
parent0aa8a01d04c8fe200b7a106878eebc3d0af9105c (diff)
downloadpostgresql-e665769e6d1e84b6650f53ed297058fc11152f7f.tar.gz
postgresql-e665769e6d1e84b6650f53ed297058fc11152f7f.zip
Sanitize IF NOT EXISTS in EXPLAIN for CTAS and matviews
IF NOT EXISTS was ignored when specified in an EXPLAIN query for CREATE MATERIALIZED VIEW or CREATE TABLE AS. Hence, if this clause was specified, the caller would get a failure if the relation already exists instead of a success with a NOTICE message. This commit makes the behavior of IF NOT EXISTS in EXPLAIN consistent with the non-EXPLAIN'd DDL queries, preventing a failure with IF NOT EXISTS if the relation to-be-created already exists. The skip is done before the SELECT query used for the relation is planned or executed, and a "dummy" plan is generated instead depending on the format used by EXPLAIN. Author: Bharath Rupireddy Reviewed-by: Zhijie Hou, Michael Paquier Discussion: https://postgr.es/m/CALj2ACVa3oJ9O_wcGd+FtHWZds04dEKcakxphGz5POVgD4wC7Q@mail.gmail.com
Diffstat (limited to 'src/backend/commands/createas.c')
-rw-r--r--src/backend/commands/createas.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 6bf6c5a3106..009896bcee7 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -239,21 +239,9 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
PlannedStmt *plan;
QueryDesc *queryDesc;
- if (stmt->if_not_exists)
- {
- Oid nspid;
-
- nspid = RangeVarGetCreationNamespace(stmt->into->rel);
-
- if (get_relname_relid(stmt->into->rel->relname, nspid))
- {
- ereport(NOTICE,
- (errcode(ERRCODE_DUPLICATE_TABLE),
- errmsg("relation \"%s\" already exists, skipping",
- stmt->into->rel->relname)));
- return InvalidObjectAddress;
- }
- }
+ /* Check if the relation exists or not */
+ if (CreateTableAsRelExists(stmt))
+ return InvalidObjectAddress;
/*
* Create the tuple receiver object and insert info it will need
@@ -401,6 +389,41 @@ GetIntoRelEFlags(IntoClause *intoClause)
}
/*
+ * CreateTableAsRelExists --- check existence of relation for CreateTableAsStmt
+ *
+ * Utility wrapper checking if the relation pending for creation in this
+ * CreateTableAsStmt query already exists or not. Returns true if the
+ * relation exists, otherwise false.
+ */
+bool
+CreateTableAsRelExists(CreateTableAsStmt *ctas)
+{
+ Oid nspid;
+ IntoClause *into = ctas->into;
+
+ nspid = RangeVarGetCreationNamespace(into->rel);
+
+ if (get_relname_relid(into->rel->relname, nspid))
+ {
+ if (!ctas->if_not_exists)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" already exists",
+ into->rel->relname)));
+
+ /* The relation exists and IF NOT EXISTS has been specified */
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" already exists, skipping",
+ into->rel->relname)));
+ return true;
+ }
+
+ /* Relation does not exist, it can be created */
+ return false;
+}
+
+/*
* CreateIntoRelDestReceiver -- create a suitable DestReceiver object
*
* intoClause will be NULL if called from CreateDestReceiver(), in which