From 75aba11ec5edf7e2f0f45a8bc67f4f20d0a33282 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Fri, 15 Feb 2019 17:12:31 +0900 Subject: [PATCH] Fix support for CREATE TABLE IF NOT EXISTS AS EXECUTE The grammar IF NOT EXISTS for CTAS is supported since 9.5 and documented as such, however the case of using EXECUTE as query has never been covered as EXECUTE CTAS statements and normal CTAS statements are parsed separately. Author: Andreas Karlsson Discussion: https://postgr.es/m/2ddcc188-e37c-a0be-32bf-a56b07c3559e@proxel.se Backpatch-through: 9.5 --- src/backend/parser/gram.y | 18 ++++++++++++++++++ src/test/regress/expected/create_table.out | 14 ++++++++++++++ src/test/regress/sql/create_table.sql | 8 ++++++++ 3 files changed, 40 insertions(+) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 1ab94931f3..9d652a3e10 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10773,11 +10773,29 @@ ExecuteStmt: EXECUTE name execute_param_clause ctas->into = $4; ctas->relkind = OBJECT_TABLE; ctas->is_select_into = false; + ctas->if_not_exists = false; /* cram additional flags into the IntoClause */ $4->rel->relpersistence = $2; $4->skipData = !($9); $$ = (Node *) ctas; } + | CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS + EXECUTE name execute_param_clause opt_with_data + { + CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); + ExecuteStmt *n = makeNode(ExecuteStmt); + n->name = $10; + n->params = $11; + ctas->query = (Node *) n; + ctas->into = $7; + ctas->relkind = OBJECT_TABLE; + ctas->is_select_into = false; + ctas->if_not_exists = true; + /* cram additional flags into the IntoClause */ + $7->rel->relpersistence = $2; + $7->skipData = !($12); + $$ = (Node *) ctas; + } ; execute_param_clause: '(' expr_list ')' { $$ = $2; } diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 8cd148601d..d2ee3f4035 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -263,6 +263,20 @@ ERROR: relation "as_select1" already exists CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; NOTICE: relation "as_select1" already exists, skipping DROP TABLE as_select1; +PREPARE select1 AS SELECT 1 as a; +CREATE TABLE as_select1 AS EXECUTE select1; +CREATE TABLE as_select1 AS EXECUTE select1; +ERROR: relation "as_select1" already exists +SELECT * FROM as_select1; + a +--- + 1 +(1 row) + +CREATE TABLE IF NOT EXISTS as_select1 AS EXECUTE select1; +NOTICE: relation "as_select1" already exists, skipping +DROP TABLE as_select1; +DEALLOCATE select1; -- create an extra wide table to test for issues related to that -- (temporarily hide query, to avoid the long CREATE TABLE stmt) \set ECHO none diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index df8b66fac4..f61cd595f7 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -278,6 +278,14 @@ CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; DROP TABLE as_select1; +PREPARE select1 AS SELECT 1 as a; +CREATE TABLE as_select1 AS EXECUTE select1; +CREATE TABLE as_select1 AS EXECUTE select1; +SELECT * FROM as_select1; +CREATE TABLE IF NOT EXISTS as_select1 AS EXECUTE select1; +DROP TABLE as_select1; +DEALLOCATE select1; + -- create an extra wide table to test for issues related to that -- (temporarily hide query, to avoid the long CREATE TABLE stmt) \set ECHO none