diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/createas.c | 18 | ||||
-rw-r--r-- | src/backend/commands/foreigncmds.c | 19 | ||||
-rw-r--r-- | src/backend/commands/schemacmds.c | 25 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 8 | ||||
-rw-r--r-- | src/backend/commands/statscmds.c | 4 | ||||
-rw-r--r-- | src/backend/commands/view.c | 16 |
6 files changed, 76 insertions, 14 deletions
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 4c1d909d380..a68d945f2e7 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -243,15 +243,27 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, if (stmt->if_not_exists) { Oid nspid; + Oid oldrelid; - nspid = RangeVarGetCreationNamespace(stmt->into->rel); + nspid = RangeVarGetCreationNamespace(into->rel); - if (get_relname_relid(stmt->into->rel->relname, nspid)) + oldrelid = get_relname_relid(into->rel->relname, nspid); + if (OidIsValid(oldrelid)) { + /* + * The relation exists and IF NOT EXISTS has been specified. + * + * If we are in an extension script, insist that the pre-existing + * object be a member of the extension, to avoid security risks. + */ + ObjectAddressSet(address, RelationRelationId, oldrelid); + checkMembershipInCurrentExtension(&address); + + /* OK to skip */ ereport(NOTICE, (errcode(ERRCODE_DUPLICATE_TABLE), errmsg("relation \"%s\" already exists, skipping", - stmt->into->rel->relname))); + into->rel->relname))); return InvalidObjectAddress; } } diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index d7bc6e35f02..bc583c689c2 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -887,13 +887,22 @@ CreateForeignServer(CreateForeignServerStmt *stmt) ownerId = GetUserId(); /* - * Check that there is no other foreign server by this name. Do nothing if - * IF NOT EXISTS was enforced. + * Check that there is no other foreign server by this name. If there is + * one, do nothing if IF NOT EXISTS was specified. */ - if (GetForeignServerByName(stmt->servername, true) != NULL) + srvId = get_foreign_server_oid(stmt->servername, true); + if (OidIsValid(srvId)) { if (stmt->if_not_exists) { + /* + * If we are in an extension script, insist that the pre-existing + * object be a member of the extension, to avoid security risks. + */ + ObjectAddressSet(myself, ForeignServerRelationId, srvId); + checkMembershipInCurrentExtension(&myself); + + /* OK to skip */ ereport(NOTICE, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("server \"%s\" already exists, skipping", @@ -1182,6 +1191,10 @@ CreateUserMapping(CreateUserMappingStmt *stmt) { if (stmt->if_not_exists) { + /* + * Since user mappings aren't members of extensions (see comments + * below), no need for checkMembershipInCurrentExtension here. + */ ereport(NOTICE, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("user mapping for \"%s\" already exists for server \"%s\", skipping", diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 6cf94a3140b..6bc4edc321f 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -113,14 +113,25 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, * 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))) + if (stmt->if_not_exists) { - ereport(NOTICE, - (errcode(ERRCODE_DUPLICATE_SCHEMA), - errmsg("schema \"%s\" already exists, skipping", - schemaName))); - return InvalidOid; + namespaceId = get_namespace_oid(schemaName, true); + if (OidIsValid(namespaceId)) + { + /* + * If we are in an extension script, insist that the pre-existing + * object be a member of the extension, to avoid security risks. + */ + ObjectAddressSet(address, NamespaceRelationId, namespaceId); + checkMembershipInCurrentExtension(&address); + + /* OK to skip */ + ereport(NOTICE, + (errcode(ERRCODE_DUPLICATE_SCHEMA), + errmsg("schema \"%s\" already exists, skipping", + schemaName))); + return InvalidOid; + } } /* diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 0960b339cab..0577184f82b 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -149,6 +149,14 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) RangeVarGetAndCheckCreationNamespace(seq->sequence, NoLock, &seqoid); if (OidIsValid(seqoid)) { + /* + * If we are in an extension script, insist that the pre-existing + * object be a member of the extension, to avoid security risks. + */ + ObjectAddressSet(address, RelationRelationId, seqoid); + checkMembershipInCurrentExtension(&address); + + /* OK to skip */ ereport(NOTICE, (errcode(ERRCODE_DUPLICATE_TABLE), errmsg("relation \"%s\" already exists, skipping", diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 5678d31d0b6..409cf28a7ef 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -173,6 +173,10 @@ CreateStatistics(CreateStatsStmt *stmt) { if (stmt->if_not_exists) { + /* + * Since stats objects aren't members of extensions (see comments + * below), no need for checkMembershipInCurrentExtension here. + */ ereport(NOTICE, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("statistics object \"%s\" already exists, skipping", diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 87ed453649b..dd7cc9703ec 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -205,7 +205,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace, CommandCounterIncrement(); /* - * Finally update the view options. + * Update the view's options. * * The new options list replaces the existing options list, even if * it's empty. @@ -218,8 +218,22 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace, /* EventTriggerAlterTableStart called by ProcessUtilitySlow */ AlterTableInternal(viewOid, atcmds, true); + /* + * There is very little to do here to update the view's dependencies. + * Most view-level dependency relationships, such as those on the + * owner, schema, and associated composite type, aren't changing. + * Because we don't allow changing type or collation of an existing + * view column, those dependencies of the existing columns don't + * change either, while the AT_AddColumnToView machinery took care of + * adding such dependencies for new view columns. The dependencies of + * the view's query could have changed arbitrarily, but that was dealt + * with inside StoreViewQuery. What remains is only to check that + * view replacement is allowed when we're creating an extension. + */ ObjectAddressSet(address, RelationRelationId, viewOid); + recordDependencyOnCurrentExtension(&address, true); + /* * Seems okay, so return the OID of the pre-existing view. */ |