diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml index 930d876..ea78304 100644 --- a/doc/src/sgml/ref/create_schema.sgml +++ b/doc/src/sgml/ref/create_schema.sgml @@ -21,8 +21,8 @@ PostgreSQL documentation -CREATE SCHEMA schema_name [ AUTHORIZATION user_name ] [ schema_element [ ... ] ] -CREATE SCHEMA AUTHORIZATION user_name [ schema_element [ ... ] ] +CREATE SCHEMA [ IF NOT EXISTS ] schema_name [ AUTHORIZATION user_name ] [ schema_element [ ... ] ] +CREATE SCHEMA [ IF NOT EXISTS ] AUTHORIZATION user_name [ schema_element [ ... ] ] @@ -60,6 +60,16 @@ CREATE SCHEMA AUTHORIZATION user_name Parameters + + IF NOT EXISTS + + + Do not throw an error if a schema with the same name already exists. + A notice is issued in this case. + + + + schema_name diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 4974025..f8a6c15 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -49,6 +49,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) Oid saved_uid; int save_sec_context; AclResult aclresult; + bool if_not_exists = stmt->if_not_exists; GetUserIdAndSecContext(&saved_uid, &save_sec_context); @@ -93,6 +94,15 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) SetUserIdAndSecContext(owner_uid, save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + /* If schema already exists, skip */ + if (OidIsValid(get_namespace_oid(schemaName, true)) && if_not_exists) { + ereport(NOTICE, + (errcode(ERRCODE_DUPLICATE_SCHEMA), + errmsg("schema \"%s\" already exists, skipping", + schemaName))); + return; + } + /* Create the schema's namespace */ namespaceId = NamespaceCreate(schemaName, owner_uid, false); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 90ea1f9..487cf9e 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -1169,8 +1169,23 @@ CreateSchemaStmt: n->schemaname = $5; n->authid = $5; n->schemaElts = $6; + 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; + n->schemaElts = $9; + n->if_not_exists = true; + $$ = (Node *)n; + } + | CREATE SCHEMA ColId OptSchemaEltList { CreateSchemaStmt *n = makeNode(CreateSchemaStmt); @@ -1178,8 +1193,20 @@ CreateSchemaStmt: n->schemaname = $3; n->authid = NULL; n->schemaElts = $4; + n->if_not_exists = false; $$ = (Node *)n; } + | CREATE SCHEMA IF_P NOT EXISTS ColId OptSchemaEltList + { + CreateSchemaStmt *n = makeNode(CreateSchemaStmt); + /* ...but not both */ + n->schemaname = $6; + n->authid = NULL; + n->schemaElts = $7; + n->if_not_exists = true; + $$ = (Node *)n; + } + ; OptSchemaName: diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index f433166..b2abdb1 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1157,6 +1157,7 @@ typedef struct CreateSchemaStmt char *schemaname; /* the name of the schema to create */ char *authid; /* the owner of the created schema */ List *schemaElts; /* schema components (list of parsenodes) */ + bool if_not_exists; /* just do nothing if schema already exists? */ } CreateSchemaStmt; typedef enum DropBehavior diff --git a/src/test/regress/expected/namespace.out b/src/test/regress/expected/namespace.out index 7c26da5..9ec5b4f 100644 --- a/src/test/regress/expected/namespace.out +++ b/src/test/regress/expected/namespace.out @@ -9,6 +9,11 @@ CREATE SCHEMA test_schema_1 a serial, b int UNIQUE ); +-- verify if schema already exists +CREATE SCHEMA test_schema_1; +ERROR: schema "test_schema_1" already exists +CREATE SCHEMA IF NOT EXISTS test_schema_1; +NOTICE: schema "test_schema_1" already exists, skipping -- verify that the objects were created SELECT COUNT(*) FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1'); diff --git a/src/test/regress/sql/namespace.sql b/src/test/regress/sql/namespace.sql index 919f72a..b776b3e 100644 --- a/src/test/regress/sql/namespace.sql +++ b/src/test/regress/sql/namespace.sql @@ -13,6 +13,9 @@ CREATE SCHEMA test_schema_1 b int UNIQUE ); +-- verify if schema already exists +CREATE SCHEMA test_schema_1; +CREATE SCHEMA IF NOT EXISTS test_schema_1; -- verify that the objects were created SELECT COUNT(*) FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1');