diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/createas.c | 16 | ||||
-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, 75 insertions, 13 deletions
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 9abbb6b5552..152c29b551a 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -393,11 +393,14 @@ bool CreateTableAsRelExists(CreateTableAsStmt *ctas) { Oid nspid; + Oid oldrelid; + ObjectAddress address; IntoClause *into = ctas->into; nspid = RangeVarGetCreationNamespace(into->rel); - if (get_relname_relid(into->rel->relname, nspid)) + oldrelid = get_relname_relid(into->rel->relname, nspid); + if (OidIsValid(oldrelid)) { if (!ctas->if_not_exists) ereport(ERROR, @@ -405,7 +408,16 @@ CreateTableAsRelExists(CreateTableAsStmt *ctas) errmsg("relation \"%s\" already exists", into->rel->relname))); - /* The relation exists and IF NOT EXISTS has been specified */ + /* + * 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", diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index ea27857bb84..91f4dd30de1 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -855,13 +855,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", @@ -1126,6 +1135,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 be3925b3b45..a583aa4304b 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -112,14 +112,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 b0b211891c3..99c9f91cba5 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -145,6 +145,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 415016969dd..7c62bebfd2d 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -181,6 +181,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 8690a3f3c64..b5a0fc02e5c 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -190,7 +190,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. @@ -203,8 +203,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. */ |