mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 21:01:48 +02:00
Add CINE option for CREATE TABLE AS and CREATE MATERIALIZED VIEW
Fabrízio de Royes Mello reviewed by Rushabh Lathia.
This commit is contained in:
parent
e311cd6ded
commit
e39b6f953e
@ -21,7 +21,7 @@ PostgreSQL documentation
|
|||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
CREATE MATERIALIZED VIEW <replaceable>table_name</replaceable>
|
CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] <replaceable>table_name</replaceable>
|
||||||
[ (<replaceable>column_name</replaceable> [, ...] ) ]
|
[ (<replaceable>column_name</replaceable> [, ...] ) ]
|
||||||
[ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
|
[ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
|
||||||
[ TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable> ]
|
[ TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable> ]
|
||||||
@ -53,6 +53,18 @@ CREATE MATERIALIZED VIEW <replaceable>table_name</replaceable>
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Parameters</title>
|
<title>Parameters</title>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>IF NOT EXISTS</></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not throw an error if a materialized view with the same name already
|
||||||
|
exists. A notice is issued in this case. Note that there is no guarantee
|
||||||
|
that the existing materialized view is anything like the one that would
|
||||||
|
have been created.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable>table_name</replaceable></term>
|
<term><replaceable>table_name</replaceable></term>
|
||||||
|
@ -21,7 +21,7 @@ PostgreSQL documentation
|
|||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE <replaceable>table_name</replaceable>
|
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable>table_name</replaceable>
|
||||||
[ (<replaceable>column_name</replaceable> [, ...] ) ]
|
[ (<replaceable>column_name</replaceable> [, ...] ) ]
|
||||||
[ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
|
[ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
|
||||||
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
|
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
|
||||||
@ -90,6 +90,17 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE <replaceable
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>IF NOT EXISTS</></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not throw an error if a relation with the same name already exists.
|
||||||
|
A notice is issued in this case. Refer to <xref linkend="sql-createtable">
|
||||||
|
for details.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable>table_name</replaceable></term>
|
<term><replaceable>table_name</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "access/sysattr.h"
|
#include "access/sysattr.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
#include "access/xlog.h"
|
#include "access/xlog.h"
|
||||||
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/toasting.h"
|
#include "catalog/toasting.h"
|
||||||
#include "commands/createas.h"
|
#include "commands/createas.h"
|
||||||
#include "commands/matview.h"
|
#include "commands/matview.h"
|
||||||
@ -86,6 +87,22 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
|
|||||||
QueryDesc *queryDesc;
|
QueryDesc *queryDesc;
|
||||||
ScanDirection dir;
|
ScanDirection dir;
|
||||||
|
|
||||||
|
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 InvalidOid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the tuple receiver object and insert info it will need
|
* Create the tuple receiver object and insert info it will need
|
||||||
*/
|
*/
|
||||||
|
@ -3317,6 +3317,7 @@ _copyCreateTableAsStmt(const CreateTableAsStmt *from)
|
|||||||
COPY_NODE_FIELD(into);
|
COPY_NODE_FIELD(into);
|
||||||
COPY_SCALAR_FIELD(relkind);
|
COPY_SCALAR_FIELD(relkind);
|
||||||
COPY_SCALAR_FIELD(is_select_into);
|
COPY_SCALAR_FIELD(is_select_into);
|
||||||
|
COPY_SCALAR_FIELD(if_not_exists);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
@ -1530,6 +1530,7 @@ _equalCreateTableAsStmt(const CreateTableAsStmt *a, const CreateTableAsStmt *b)
|
|||||||
COMPARE_NODE_FIELD(into);
|
COMPARE_NODE_FIELD(into);
|
||||||
COMPARE_SCALAR_FIELD(relkind);
|
COMPARE_SCALAR_FIELD(relkind);
|
||||||
COMPARE_SCALAR_FIELD(is_select_into);
|
COMPARE_SCALAR_FIELD(is_select_into);
|
||||||
|
COMPARE_SCALAR_FIELD(if_not_exists);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3401,11 +3401,25 @@ CreateAsStmt:
|
|||||||
ctas->into = $4;
|
ctas->into = $4;
|
||||||
ctas->relkind = OBJECT_TABLE;
|
ctas->relkind = OBJECT_TABLE;
|
||||||
ctas->is_select_into = false;
|
ctas->is_select_into = false;
|
||||||
|
ctas->if_not_exists = false;
|
||||||
/* cram additional flags into the IntoClause */
|
/* cram additional flags into the IntoClause */
|
||||||
$4->rel->relpersistence = $2;
|
$4->rel->relpersistence = $2;
|
||||||
$4->skipData = !($7);
|
$4->skipData = !($7);
|
||||||
$$ = (Node *) ctas;
|
$$ = (Node *) ctas;
|
||||||
}
|
}
|
||||||
|
| CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS SelectStmt opt_with_data
|
||||||
|
{
|
||||||
|
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
|
||||||
|
ctas->query = $9;
|
||||||
|
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 = !($10);
|
||||||
|
$$ = (Node *) ctas;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
create_as_target:
|
create_as_target:
|
||||||
@ -3444,11 +3458,25 @@ CreateMatViewStmt:
|
|||||||
ctas->into = $5;
|
ctas->into = $5;
|
||||||
ctas->relkind = OBJECT_MATVIEW;
|
ctas->relkind = OBJECT_MATVIEW;
|
||||||
ctas->is_select_into = false;
|
ctas->is_select_into = false;
|
||||||
|
ctas->if_not_exists = false;
|
||||||
/* cram additional flags into the IntoClause */
|
/* cram additional flags into the IntoClause */
|
||||||
$5->rel->relpersistence = $2;
|
$5->rel->relpersistence = $2;
|
||||||
$5->skipData = !($8);
|
$5->skipData = !($8);
|
||||||
$$ = (Node *) ctas;
|
$$ = (Node *) ctas;
|
||||||
}
|
}
|
||||||
|
| CREATE OptNoLog MATERIALIZED VIEW IF_P NOT EXISTS create_mv_target AS SelectStmt opt_with_data
|
||||||
|
{
|
||||||
|
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
|
||||||
|
ctas->query = $10;
|
||||||
|
ctas->into = $8;
|
||||||
|
ctas->relkind = OBJECT_MATVIEW;
|
||||||
|
ctas->is_select_into = false;
|
||||||
|
ctas->if_not_exists = true;
|
||||||
|
/* cram additional flags into the IntoClause */
|
||||||
|
$8->rel->relpersistence = $2;
|
||||||
|
$8->skipData = !($11);
|
||||||
|
$$ = (Node *) ctas;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
create_mv_target:
|
create_mv_target:
|
||||||
|
@ -2652,6 +2652,7 @@ typedef struct CreateTableAsStmt
|
|||||||
IntoClause *into; /* destination table */
|
IntoClause *into; /* destination table */
|
||||||
ObjectType relkind; /* OBJECT_TABLE or OBJECT_MATVIEW */
|
ObjectType relkind; /* OBJECT_TABLE or OBJECT_MATVIEW */
|
||||||
bool is_select_into; /* it was written as SELECT INTO */
|
bool is_select_into; /* it was written as SELECT INTO */
|
||||||
|
bool if_not_exists; /* just do nothing if it already exists? */
|
||||||
} CreateTableAsStmt;
|
} CreateTableAsStmt;
|
||||||
|
|
||||||
/* ----------------------
|
/* ----------------------
|
||||||
|
@ -218,3 +218,9 @@ CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK
|
|||||||
CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK
|
CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK
|
||||||
ERROR: cannot create temporary relation in non-temporary schema
|
ERROR: cannot create temporary relation in non-temporary schema
|
||||||
DROP TABLE unlogged1, public.unlogged2;
|
DROP TABLE unlogged1, public.unlogged2;
|
||||||
|
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
|
||||||
|
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
|
||||||
|
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;
|
||||||
|
@ -508,6 +508,10 @@ SET ROLE user_dw;
|
|||||||
CREATE TABLE foo_data AS SELECT i, md5(random()::text)
|
CREATE TABLE foo_data AS SELECT i, md5(random()::text)
|
||||||
FROM generate_series(1, 10) i;
|
FROM generate_series(1, 10) i;
|
||||||
CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
|
CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
|
||||||
|
CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
|
||||||
|
ERROR: relation "mv_foo" already exists
|
||||||
|
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_foo AS SELECT * FROM foo_data;
|
||||||
|
NOTICE: relation "mv_foo" already exists, skipping
|
||||||
CREATE UNIQUE INDEX ON mv_foo (i);
|
CREATE UNIQUE INDEX ON mv_foo (i);
|
||||||
RESET ROLE;
|
RESET ROLE;
|
||||||
REFRESH MATERIALIZED VIEW mv_foo;
|
REFRESH MATERIALIZED VIEW mv_foo;
|
||||||
|
@ -254,3 +254,8 @@ CREATE TEMP TABLE explicitly_temp (a int primary key); -- also OK
|
|||||||
CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK
|
CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK
|
||||||
CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK
|
CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK
|
||||||
DROP TABLE unlogged1, public.unlogged2;
|
DROP TABLE unlogged1, public.unlogged2;
|
||||||
|
|
||||||
|
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
|
||||||
|
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;
|
||||||
|
@ -201,6 +201,8 @@ SET ROLE user_dw;
|
|||||||
CREATE TABLE foo_data AS SELECT i, md5(random()::text)
|
CREATE TABLE foo_data AS SELECT i, md5(random()::text)
|
||||||
FROM generate_series(1, 10) i;
|
FROM generate_series(1, 10) i;
|
||||||
CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
|
CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
|
||||||
|
CREATE MATERIALIZED VIEW mv_foo AS SELECT * FROM foo_data;
|
||||||
|
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_foo AS SELECT * FROM foo_data;
|
||||||
CREATE UNIQUE INDEX ON mv_foo (i);
|
CREATE UNIQUE INDEX ON mv_foo (i);
|
||||||
RESET ROLE;
|
RESET ROLE;
|
||||||
REFRESH MATERIALIZED VIEW mv_foo;
|
REFRESH MATERIALIZED VIEW mv_foo;
|
||||||
|
Loading…
Reference in New Issue
Block a user