Fix support for CREATE TABLE IF NOT EXISTS AS EXECUTE
authorMichael Paquier
Fri, 15 Feb 2019 08:12:36 +0000 (17:12 +0900)
committerMichael Paquier
Fri, 15 Feb 2019 08:12:36 +0000 (17:12 +0900)
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
src/test/regress/expected/create_table.out
src/test/regress/sql/create_table.sql

index a97f51ce37c8250d3d2c3e09c4018b9cd03104af..a8ce22f31175cc6d78103cbe8a3a3a152a6060ca 100644 (file)
@@ -10383,11 +10383,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; }
index 28c9d2df898adb382edd0146677199c97b9ad9d4..ab82a29560624a55f4125e32d326d47c0bafe7ec 100644 (file)
@@ -258,6 +258,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;
 -- check that the oid column is added before the primary key is checked
 CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
 DROP TABLE oid_pk;
index 7849139ca15cd0f6dfcc526ec2ba757d2f611ee9..137c0db5b3fad568a4384dd0b34f2515021285ce 100644 (file)
@@ -274,6 +274,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;
+
 -- check that the oid column is added before the primary key is checked
 CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
 DROP TABLE oid_pk;