diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8473c9e7f44..4953def029b 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -366,7 +366,9 @@ static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename, LOCKMODE lockmode); static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode); -static void ATExecSetRelOptions(Relation rel, List *defList, bool isReset, LOCKMODE lockmode); +static void ATExecSetRelOptions(Relation rel, List *defList, + AlterTableType operation, + LOCKMODE lockmode); static void ATExecEnableDisableTrigger(Relation rel, char *trigname, char fires_when, bool skip_system, LOCKMODE lockmode); static void ATExecEnableDisableRule(Relation rel, char *rulename, @@ -2866,6 +2868,7 @@ AlterTableGetLockLevel(List *cmds) case AT_DropCluster: case AT_SetRelOptions: case AT_ResetRelOptions: + case AT_ReplaceRelOptions: case AT_SetOptions: case AT_ResetOptions: case AT_SetStorage: @@ -3094,8 +3097,9 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_MISC; /* doesn't actually matter */ break; case AT_SetRelOptions: /* SET (...) */ - case AT_ResetRelOptions: /* RESET (...) */ - ATSimplePermissions(rel, ATT_TABLE | ATT_INDEX); + case AT_ResetRelOptions: /* RESET (...) */ + case AT_ReplaceRelOptions: /* reset them all, then set just these */ + ATSimplePermissions(rel, ATT_TABLE | ATT_INDEX | ATT_VIEW); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_MISC; @@ -3338,12 +3342,10 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, */ break; case AT_SetRelOptions: /* SET (...) */ - ATExecSetRelOptions(rel, (List *) cmd->def, false, lockmode); - break; case AT_ResetRelOptions: /* RESET (...) */ - ATExecSetRelOptions(rel, (List *) cmd->def, true, lockmode); + case AT_ReplaceRelOptions: /* replace entire option list */ + ATExecSetRelOptions(rel, (List *) cmd->def, cmd->subtype, lockmode); break; - case AT_EnableTrig: /* ENABLE TRIGGER name */ ATExecEnableDisableTrigger(rel, cmd->name, TRIGGER_FIRES_ON_ORIGIN, false, lockmode); @@ -8271,10 +8273,11 @@ ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename, L } /* - * ALTER TABLE/INDEX SET (...) or RESET (...) + * Set, reset, or replace reloptions. */ static void -ATExecSetRelOptions(Relation rel, List *defList, bool isReset, LOCKMODE lockmode) +ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, + LOCKMODE lockmode) { Oid relid; Relation pgclass; @@ -8288,28 +8291,44 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset, LOCKMODE lockmode bool repl_repl[Natts_pg_class]; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; - if (defList == NIL) + if (defList == NIL && operation != AT_ReplaceRelOptions) return; /* nothing to do */ pgclass = heap_open(RelationRelationId, RowExclusiveLock); - /* Get the old reloptions */ + /* Fetch heap tuple */ relid = RelationGetRelid(rel); tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull); + if (operation == AT_ReplaceRelOptions) + { + /* + * If we're supposed to replace the reloptions list, we just pretend + * there were none before. + */ + datum = (Datum) 0; + isnull = true; + } + else + { + /* Get the old reloptions */ + datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, + &isnull); + } /* Generate new proposed reloptions (text array) */ newOptions = transformRelOptions(isnull ? (Datum) 0 : datum, - defList, NULL, validnsps, false, isReset); + defList, NULL, validnsps, false, + operation == AT_ResetRelOptions); /* Validate */ switch (rel->rd_rel->relkind) { case RELKIND_RELATION: case RELKIND_TOASTVALUE: + case RELKIND_VIEW: (void) heap_reloptions(rel->rd_rel->relkind, newOptions, true); break; case RELKIND_INDEX: @@ -8357,15 +8376,30 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset, LOCKMODE lockmode toastrel = heap_open(toastid, lockmode); - /* Get the old reloptions */ + /* Fetch heap tuple */ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", toastid); - datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull); + if (operation == AT_ReplaceRelOptions) + { + /* + * If we're supposed to replace the reloptions list, we just + * pretend there were none before. + */ + datum = (Datum) 0; + isnull = true; + } + else + { + /* Get the old reloptions */ + datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, + &isnull); + } newOptions = transformRelOptions(isnull ? (Datum) 0 : datum, - defList, "toast", validnsps, false, isReset); + defList, "toast", validnsps, false, + operation == AT_ResetRelOptions); (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true); |