mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Support CREATE SCHEMA IF NOT EXISTS.
Per discussion, schema-element subcommands are not allowed together with this option, since it's not very obvious what should happen to the element objects. Fabrízio de Royes Mello
This commit is contained in:
@ -23,6 +23,8 @@ PostgreSQL documentation
|
|||||||
<synopsis>
|
<synopsis>
|
||||||
CREATE SCHEMA <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="parameter">user_name</replaceable> ] [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
|
CREATE SCHEMA <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="parameter">user_name</replaceable> ] [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
|
||||||
CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">user_name</replaceable> [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
|
CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">user_name</replaceable> [ <replaceable class="parameter">schema_element</replaceable> [ ... ] ]
|
||||||
|
CREATE SCHEMA IF NOT EXISTS <replaceable class="parameter">schema_name</replaceable> [ AUTHORIZATION <replaceable class="parameter">user_name</replaceable> ]
|
||||||
|
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION <replaceable class="parameter">user_name</replaceable>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@ -98,6 +100,17 @@ CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">user_name</replaceabl
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>IF NOT EXISTS</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do nothing (except issuing a notice) if a schema with the same name
|
||||||
|
already exists. <replaceable class="parameter">schema_element</>
|
||||||
|
subcommands cannot be included when this option is used.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -129,6 +142,15 @@ CREATE SCHEMA AUTHORIZATION joe;
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Create a schema named <literal>test</> that will be owned by user
|
||||||
|
<literal>joe</>, unless there already is a schema named <literal>test</>.
|
||||||
|
(It does not matter whether <literal>joe</> owns the pre-existing schema.)
|
||||||
|
<programlisting>
|
||||||
|
CREATE SCHEMA IF NOT EXISTS test AUTHORIZATION joe;
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Create a schema and create a table and view within it:
|
Create a schema and create a table and view within it:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
@ -177,6 +199,11 @@ CREATE VIEW hollywood.winners AS
|
|||||||
schema owner. This can happen only if the schema owner grants the
|
schema owner. This can happen only if the schema owner grants the
|
||||||
<literal>CREATE</> privilege on his schema to someone else.
|
<literal>CREATE</> privilege on his schema to someone else.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <literal>IF NOT EXISTS</literal> option is a
|
||||||
|
<productname>PostgreSQL</productname> extension.
|
||||||
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -1376,6 +1376,7 @@ CreateExtension(CreateExtensionStmt *stmt)
|
|||||||
csstmt->schemaname = schemaName;
|
csstmt->schemaname = schemaName;
|
||||||
csstmt->authid = NULL; /* will be created by current user */
|
csstmt->authid = NULL; /* will be created by current user */
|
||||||
csstmt->schemaElts = NIL;
|
csstmt->schemaElts = NIL;
|
||||||
|
csstmt->if_not_exists = false;
|
||||||
CreateSchemaCommand(csstmt, NULL);
|
CreateSchemaCommand(csstmt, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -83,6 +83,23 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
|||||||
errmsg("unacceptable schema name \"%s\"", schemaName),
|
errmsg("unacceptable schema name \"%s\"", schemaName),
|
||||||
errdetail("The prefix \"pg_\" is reserved for system schemas.")));
|
errdetail("The prefix \"pg_\" is reserved for system schemas.")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If if_not_exists was given and the schema already exists, bail out.
|
||||||
|
* (Note: we needn't check this when not if_not_exists, because
|
||||||
|
* NamespaceCreate will complain anyway.) We could do this before making
|
||||||
|
* the permissions checks, but since CREATE TABLE IF NOT EXISTS makes its
|
||||||
|
* creation-permission check first, we do likewise.
|
||||||
|
*/
|
||||||
|
if (stmt->if_not_exists &&
|
||||||
|
SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(schemaName)))
|
||||||
|
{
|
||||||
|
ereport(NOTICE,
|
||||||
|
(errcode(ERRCODE_DUPLICATE_SCHEMA),
|
||||||
|
errmsg("schema \"%s\" already exists, skipping",
|
||||||
|
schemaName)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the requested authorization is different from the current user,
|
* If the requested authorization is different from the current user,
|
||||||
* temporarily set the current user so that the object(s) will be created
|
* temporarily set the current user so that the object(s) will be created
|
||||||
|
@ -3613,6 +3613,7 @@ _copyCreateSchemaStmt(const CreateSchemaStmt *from)
|
|||||||
COPY_STRING_FIELD(schemaname);
|
COPY_STRING_FIELD(schemaname);
|
||||||
COPY_STRING_FIELD(authid);
|
COPY_STRING_FIELD(authid);
|
||||||
COPY_NODE_FIELD(schemaElts);
|
COPY_NODE_FIELD(schemaElts);
|
||||||
|
COPY_SCALAR_FIELD(if_not_exists);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
@ -1909,6 +1909,7 @@ _equalCreateSchemaStmt(const CreateSchemaStmt *a, const CreateSchemaStmt *b)
|
|||||||
COMPARE_STRING_FIELD(schemaname);
|
COMPARE_STRING_FIELD(schemaname);
|
||||||
COMPARE_STRING_FIELD(authid);
|
COMPARE_STRING_FIELD(authid);
|
||||||
COMPARE_NODE_FIELD(schemaElts);
|
COMPARE_NODE_FIELD(schemaElts);
|
||||||
|
COMPARE_SCALAR_FIELD(if_not_exists);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1169,6 +1169,7 @@ CreateSchemaStmt:
|
|||||||
n->schemaname = $5;
|
n->schemaname = $5;
|
||||||
n->authid = $5;
|
n->authid = $5;
|
||||||
n->schemaElts = $6;
|
n->schemaElts = $6;
|
||||||
|
n->if_not_exists = false;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| CREATE SCHEMA ColId OptSchemaEltList
|
| CREATE SCHEMA ColId OptSchemaEltList
|
||||||
@ -1178,6 +1179,40 @@ CreateSchemaStmt:
|
|||||||
n->schemaname = $3;
|
n->schemaname = $3;
|
||||||
n->authid = NULL;
|
n->authid = NULL;
|
||||||
n->schemaElts = $4;
|
n->schemaElts = $4;
|
||||||
|
n->if_not_exists = false;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
| CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
|
||||||
|
{
|
||||||
|
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
|
||||||
|
/* One can omit the schema name or the authorization id. */
|
||||||
|
if ($6 != NULL)
|
||||||
|
n->schemaname = $6;
|
||||||
|
else
|
||||||
|
n->schemaname = $8;
|
||||||
|
n->authid = $8;
|
||||||
|
if ($9 != NIL)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
|
||||||
|
parser_errposition(@9)));
|
||||||
|
n->schemaElts = $9;
|
||||||
|
n->if_not_exists = true;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
| CREATE SCHEMA IF_P NOT EXISTS ColId OptSchemaEltList
|
||||||
|
{
|
||||||
|
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
|
||||||
|
/* ...but not both */
|
||||||
|
n->schemaname = $6;
|
||||||
|
n->authid = NULL;
|
||||||
|
if ($7 != NIL)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
|
||||||
|
parser_errposition(@7)));
|
||||||
|
n->schemaElts = $7;
|
||||||
|
n->if_not_exists = true;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -1157,6 +1157,7 @@ typedef struct CreateSchemaStmt
|
|||||||
char *schemaname; /* the name of the schema to create */
|
char *schemaname; /* the name of the schema to create */
|
||||||
char *authid; /* the owner of the created schema */
|
char *authid; /* the owner of the created schema */
|
||||||
List *schemaElts; /* schema components (list of parsenodes) */
|
List *schemaElts; /* schema components (list of parsenodes) */
|
||||||
|
bool if_not_exists; /* just do nothing if schema already exists? */
|
||||||
} CreateSchemaStmt;
|
} CreateSchemaStmt;
|
||||||
|
|
||||||
typedef enum DropBehavior
|
typedef enum DropBehavior
|
||||||
|
@ -36,6 +36,19 @@ SELECT * FROM test_schema_1.abc_view;
|
|||||||
4 |
|
4 |
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
|
-- test IF NOT EXISTS cases
|
||||||
|
CREATE SCHEMA test_schema_1; -- fail, already exists
|
||||||
|
ERROR: schema "test_schema_1" already exists
|
||||||
|
CREATE SCHEMA IF NOT EXISTS test_schema_1; -- ok with notice
|
||||||
|
NOTICE: schema "test_schema_1" already exists, skipping
|
||||||
|
CREATE SCHEMA IF NOT EXISTS test_schema_1 -- fail, disallowed
|
||||||
|
CREATE TABLE abc (
|
||||||
|
a serial,
|
||||||
|
b int UNIQUE
|
||||||
|
);
|
||||||
|
ERROR: CREATE SCHEMA IF NOT EXISTS cannot include schema elements
|
||||||
|
LINE 1: CREATE SCHEMA IF NOT EXISTS test_schema_1
|
||||||
|
^
|
||||||
DROP SCHEMA test_schema_1 CASCADE;
|
DROP SCHEMA test_schema_1 CASCADE;
|
||||||
NOTICE: drop cascades to 2 other objects
|
NOTICE: drop cascades to 2 other objects
|
||||||
DETAIL: drop cascades to table test_schema_1.abc
|
DETAIL: drop cascades to table test_schema_1.abc
|
||||||
|
@ -24,6 +24,15 @@ INSERT INTO test_schema_1.abc DEFAULT VALUES;
|
|||||||
SELECT * FROM test_schema_1.abc;
|
SELECT * FROM test_schema_1.abc;
|
||||||
SELECT * FROM test_schema_1.abc_view;
|
SELECT * FROM test_schema_1.abc_view;
|
||||||
|
|
||||||
|
-- test IF NOT EXISTS cases
|
||||||
|
CREATE SCHEMA test_schema_1; -- fail, already exists
|
||||||
|
CREATE SCHEMA IF NOT EXISTS test_schema_1; -- ok with notice
|
||||||
|
CREATE SCHEMA IF NOT EXISTS test_schema_1 -- fail, disallowed
|
||||||
|
CREATE TABLE abc (
|
||||||
|
a serial,
|
||||||
|
b int UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
DROP SCHEMA test_schema_1 CASCADE;
|
DROP SCHEMA test_schema_1 CASCADE;
|
||||||
|
|
||||||
-- verify that the objects were dropped
|
-- verify that the objects were dropped
|
||||||
|
Reference in New Issue
Block a user