|
|
|
@ -398,8 +398,7 @@ static void ATRewriteTables(AlterTableStmt *parsetree,
|
|
|
|
|
AlterTableUtilityContext *context);
|
|
|
|
|
static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode);
|
|
|
|
|
static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
|
|
|
|
|
static void ATSimplePermissions(Relation rel, int allowed_targets);
|
|
|
|
|
static void ATWrongRelkindError(Relation rel, int allowed_targets);
|
|
|
|
|
static void ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets);
|
|
|
|
|
static void ATSimpleRecursion(List **wqueue, Relation rel,
|
|
|
|
|
AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode,
|
|
|
|
|
AlterTableUtilityContext *context);
|
|
|
|
@ -3394,8 +3393,9 @@ renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
|
|
|
|
|
relkind != RELKIND_PARTITIONED_TABLE)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("\"%s\" is not a table, view, materialized view, composite type, index, or foreign table",
|
|
|
|
|
NameStr(classform->relname))));
|
|
|
|
|
errmsg("cannot rename columns of relation \"%s\"",
|
|
|
|
|
NameStr(classform->relname)),
|
|
|
|
|
errdetail_relkind_not_supported(relkind)));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* permissions checking. only the owner of a class can change its schema.
|
|
|
|
@ -4422,7 +4422,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
switch (cmd->subtype)
|
|
|
|
|
{
|
|
|
|
|
case AT_AddColumn: /* ADD COLUMN */
|
|
|
|
|
ATSimplePermissions(rel,
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel,
|
|
|
|
|
ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATPrepAddColumn(wqueue, rel, recurse, recursing, false, cmd,
|
|
|
|
|
lockmode, context);
|
|
|
|
@ -4430,7 +4430,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_ADD_COL;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AddColumnToView: /* add column via CREATE OR REPLACE VIEW */
|
|
|
|
|
ATSimplePermissions(rel, ATT_VIEW);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_VIEW);
|
|
|
|
|
ATPrepAddColumn(wqueue, rel, recurse, recursing, true, cmd,
|
|
|
|
|
lockmode, context);
|
|
|
|
|
/* Recursion occurs during execution phase */
|
|
|
|
@ -4444,7 +4444,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
* substitutes default values into INSERTs before it expands
|
|
|
|
|
* rules.
|
|
|
|
|
*/
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = cmd->def ? AT_PASS_ADD_OTHERCONSTR : AT_PASS_DROP;
|
|
|
|
@ -4452,77 +4452,77 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
case AT_CookedColumnDefault: /* add a pre-cooked default */
|
|
|
|
|
/* This is currently used only in CREATE TABLE */
|
|
|
|
|
/* (so the permission check really isn't necessary) */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
pass = AT_PASS_ADD_OTHERCONSTR;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AddIdentity:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
pass = AT_PASS_ADD_OTHERCONSTR;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetIdentity:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* This should run after AddIdentity, so do it in MISC pass */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropIdentity:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
pass = AT_PASS_DROP;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATPrepDropNotNull(rel, recurse, recursing);
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
pass = AT_PASS_DROP;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* Need command-specific recursion decision */
|
|
|
|
|
ATPrepSetNotNull(wqueue, rel, cmd, recurse, recursing,
|
|
|
|
|
lockmode, context);
|
|
|
|
|
pass = AT_PASS_COL_ATTRS;
|
|
|
|
|
break;
|
|
|
|
|
case AT_CheckNotNull: /* check column is already marked NOT NULL */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_COL_ATTRS;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropExpression: /* ALTER COLUMN DROP EXPRESSION */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
ATPrepDropExpression(rel, cmd, recurse, recursing, lockmode);
|
|
|
|
|
pass = AT_PASS_DROP;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetOptions: /* ALTER COLUMN SET ( options ) */
|
|
|
|
|
case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropColumn: /* DROP COLUMN */
|
|
|
|
|
ATSimplePermissions(rel,
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel,
|
|
|
|
|
ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd,
|
|
|
|
|
lockmode, context);
|
|
|
|
@ -4530,13 +4530,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_DROP;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AddIndex: /* ADD INDEX */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_ADD_INDEX;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AddConstraint: /* ADD CONSTRAINT */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* Recursion occurs during execution phase */
|
|
|
|
|
/* No command-specific prep needed except saving recurse flag */
|
|
|
|
|
if (recurse)
|
|
|
|
@ -4544,13 +4544,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_ADD_CONSTR;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_ADD_INDEXCONSTR;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropConstraint: /* DROP CONSTRAINT */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATCheckPartitionsNotInUse(rel, lockmode);
|
|
|
|
|
/* Other recursion occurs during execution phase */
|
|
|
|
|
/* No command-specific prep needed except saving recurse flag */
|
|
|
|
@ -4559,7 +4559,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_DROP;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AlterColumnType: /* ALTER COLUMN TYPE */
|
|
|
|
|
ATSimplePermissions(rel,
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel,
|
|
|
|
|
ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* See comments for ATPrepAlterColumnType */
|
|
|
|
|
cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, recurse, lockmode,
|
|
|
|
@ -4571,7 +4571,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_ALTER_TYPE;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AlterColumnGenericOptions:
|
|
|
|
|
ATSimplePermissions(rel, ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
@ -4583,13 +4583,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
break;
|
|
|
|
|
case AT_ClusterOn: /* CLUSTER ON */
|
|
|
|
|
case AT_DropCluster: /* SET WITHOUT CLUSTER */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
|
|
|
|
|
/* These commands never recurse */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetLogged: /* SET LOGGED */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
if (tab->chgPersistence)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
@ -4604,7 +4604,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetUnLogged: /* SET UNLOGGED */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
if (tab->chgPersistence)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
@ -4619,11 +4619,11 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropOids: /* SET WITHOUT OIDS */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
pass = AT_PASS_DROP;
|
|
|
|
|
break;
|
|
|
|
|
case AT_SetTableSpace: /* SET TABLESPACE */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX |
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX |
|
|
|
|
|
ATT_PARTITIONED_INDEX);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
ATPrepSetTableSpace(tab, rel, cmd->name, lockmode);
|
|
|
|
@ -4632,30 +4632,30 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
case AT_SetRelOptions: /* SET (...) */
|
|
|
|
|
case AT_ResetRelOptions: /* RESET (...) */
|
|
|
|
|
case AT_ReplaceRelOptions: /* reset them all, then set just these */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AddInherit: /* INHERIT */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
ATPrepAddInherit(rel);
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DropInherit: /* NO INHERIT */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AlterConstraint: /* ALTER CONSTRAINT */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
/* Recursion occurs during execution phase */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
/* Recursion occurs during execution phase */
|
|
|
|
|
/* No command-specific prep needed except saving recurse flag */
|
|
|
|
|
if (recurse)
|
|
|
|
@ -4663,7 +4663,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_ReplicaIdentity: /* REPLICA IDENTITY ... */
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
/* This command never recurses */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
@ -4676,7 +4676,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
case AT_DisableTrig: /* DISABLE TRIGGER variants */
|
|
|
|
|
case AT_DisableTrigAll:
|
|
|
|
|
case AT_DisableTrigUser:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
|
|
|
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
@ -4691,28 +4691,28 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|
|
|
|
case AT_DisableRowSecurity:
|
|
|
|
|
case AT_ForceRowSecurity:
|
|
|
|
|
case AT_NoForceRowSecurity:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
/* These commands never recurse */
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_GenericOptions:
|
|
|
|
|
ATSimplePermissions(rel, ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_FOREIGN_TABLE);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_AttachPartition:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_PARTITIONED_INDEX);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_INDEX);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DetachPartition:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
|
case AT_DetachPartitionFinalize:
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE);
|
|
|
|
|
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
|
|
|
|
|
/* No command-specific prep needed */
|
|
|
|
|
pass = AT_PASS_MISC;
|
|
|
|
|
break;
|
|
|
|
@ -5941,6 +5941,145 @@ ATGetQueueEntry(List **wqueue, Relation rel)
|
|
|
|
|
return tab;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
alter_table_type_to_string(AlterTableType cmdtype)
|
|
|
|
|
{
|
|
|
|
|
switch (cmdtype)
|
|
|
|
|
{
|
|
|
|
|
case AT_AddColumn:
|
|
|
|
|
case AT_AddColumnRecurse:
|
|
|
|
|
case AT_AddColumnToView:
|
|
|
|
|
return "ADD COLUMN";
|
|
|
|
|
case AT_ColumnDefault:
|
|
|
|
|
case AT_CookedColumnDefault:
|
|
|
|
|
return "ALTER COLUMN ... SET DEFAULT";
|
|
|
|
|
case AT_DropNotNull:
|
|
|
|
|
return "ALTER COLUMN ... DROP NOT NULL";
|
|
|
|
|
case AT_SetNotNull:
|
|
|
|
|
return "ALTER COLUMN ... SET NOT NULL";
|
|
|
|
|
case AT_DropExpression:
|
|
|
|
|
return "ALTER COLUMN ... DROP EXPRESSION";
|
|
|
|
|
case AT_CheckNotNull:
|
|
|
|
|
return NULL; /* not real grammar */
|
|
|
|
|
case AT_SetStatistics:
|
|
|
|
|
return "ALTER COLUMN ... SET STATISTICS";
|
|
|
|
|
case AT_SetOptions:
|
|
|
|
|
return "ALTER COLUMN ... SET";
|
|
|
|
|
case AT_ResetOptions:
|
|
|
|
|
return "ALTER COLUMN ... RESET";
|
|
|
|
|
case AT_SetStorage:
|
|
|
|
|
return "ALTER COLUMN ... SET STORAGE";
|
|
|
|
|
case AT_SetCompression:
|
|
|
|
|
return "ALTER COLUMN ... SET COMPRESSION";
|
|
|
|
|
case AT_DropColumn:
|
|
|
|
|
case AT_DropColumnRecurse:
|
|
|
|
|
return "DROP COLUMN";
|
|
|
|
|
case AT_AddIndex:
|
|
|
|
|
case AT_ReAddIndex:
|
|
|
|
|
return NULL; /* not real grammar */
|
|
|
|
|
case AT_AddConstraint:
|
|
|
|
|
case AT_AddConstraintRecurse:
|
|
|
|
|
case AT_ReAddConstraint:
|
|
|
|
|
case AT_ReAddDomainConstraint:
|
|
|
|
|
case AT_AddIndexConstraint:
|
|
|
|
|
return "ADD CONSTRAINT";
|
|
|
|
|
case AT_AlterConstraint:
|
|
|
|
|
return "ALTER CONSTRAINT";
|
|
|
|
|
case AT_ValidateConstraint:
|
|
|
|
|
case AT_ValidateConstraintRecurse:
|
|
|
|
|
return "VALIDATE CONSTRAINT";
|
|
|
|
|
case AT_DropConstraint:
|
|
|
|
|
case AT_DropConstraintRecurse:
|
|
|
|
|
return "DROP CONSTRAINT";
|
|
|
|
|
case AT_ReAddComment:
|
|
|
|
|
return NULL; /* not real grammar */
|
|
|
|
|
case AT_AlterColumnType:
|
|
|
|
|
return "ALTER COLUMN ... SET DATA TYPE";
|
|
|
|
|
case AT_AlterColumnGenericOptions:
|
|
|
|
|
return "ALTER COLUMN ... OPTIONS";
|
|
|
|
|
case AT_ChangeOwner:
|
|
|
|
|
return "OWNER TO";
|
|
|
|
|
case AT_ClusterOn:
|
|
|
|
|
return "CLUSTER ON";
|
|
|
|
|
case AT_DropCluster:
|
|
|
|
|
return "SET WITHOUT CLUSTER";
|
|
|
|
|
case AT_SetLogged:
|
|
|
|
|
return "SET LOGGED";
|
|
|
|
|
case AT_SetUnLogged:
|
|
|
|
|
return "SET UNLOGGED";
|
|
|
|
|
case AT_DropOids:
|
|
|
|
|
return "SET WITHOUT OIDS";
|
|
|
|
|
case AT_SetTableSpace:
|
|
|
|
|
return "SET TABLESPACE";
|
|
|
|
|
case AT_SetRelOptions:
|
|
|
|
|
return "SET";
|
|
|
|
|
case AT_ResetRelOptions:
|
|
|
|
|
return "RESET";
|
|
|
|
|
case AT_ReplaceRelOptions:
|
|
|
|
|
return NULL; /* not real grammar */
|
|
|
|
|
case AT_EnableTrig:
|
|
|
|
|
return "ENABLE TRIGGER";
|
|
|
|
|
case AT_EnableAlwaysTrig:
|
|
|
|
|
return "ENABLE ALWAYS TRIGGER";
|
|
|
|
|
case AT_EnableReplicaTrig:
|
|
|
|
|
return "ENABLE REPLICA TRIGGER";
|
|
|
|
|
case AT_DisableTrig:
|
|
|
|
|
return "DISABLE TRIGGER";
|
|
|
|
|
case AT_EnableTrigAll:
|
|
|
|
|
return "ENABLE TRIGGER ALL";
|
|
|
|
|
case AT_DisableTrigAll:
|
|
|
|
|
return "DISABLE TRIGGER ALL";
|
|
|
|
|
case AT_EnableTrigUser:
|
|
|
|
|
return "ENABLE TRIGGER USER";
|
|
|
|
|
case AT_DisableTrigUser:
|
|
|
|
|
return "DISABLE TRIGGER USER";
|
|
|
|
|
case AT_EnableRule:
|
|
|
|
|
return "ENABLE RULE";
|
|
|
|
|
case AT_EnableAlwaysRule:
|
|
|
|
|
return "ENABLE ALWAYS RULE";
|
|
|
|
|
case AT_EnableReplicaRule:
|
|
|
|
|
return "ENABLE REPLICA RULE";
|
|
|
|
|
case AT_DisableRule:
|
|
|
|
|
return "DISABLE RULE";
|
|
|
|
|
case AT_AddInherit:
|
|
|
|
|
return "INHERIT";
|
|
|
|
|
case AT_DropInherit:
|
|
|
|
|
return "NO INHERIT";
|
|
|
|
|
case AT_AddOf:
|
|
|
|
|
return "OF";
|
|
|
|
|
case AT_DropOf:
|
|
|
|
|
return "NOT OF";
|
|
|
|
|
case AT_ReplicaIdentity:
|
|
|
|
|
return "REPLICA IDENTITY";
|
|
|
|
|
case AT_EnableRowSecurity:
|
|
|
|
|
return "ENABLE ROW SECURITY";
|
|
|
|
|
case AT_DisableRowSecurity:
|
|
|
|
|
return "DISABLE ROW SECURITY";
|
|
|
|
|
case AT_ForceRowSecurity:
|
|
|
|
|
return "FORCE ROW SECURITY";
|
|
|
|
|
case AT_NoForceRowSecurity:
|
|
|
|
|
return "NO FORCE ROW SECURITY";
|
|
|
|
|
case AT_GenericOptions:
|
|
|
|
|
return "OPTIONS";
|
|
|
|
|
case AT_AttachPartition:
|
|
|
|
|
return "ATTACH PARTITION";
|
|
|
|
|
case AT_DetachPartition:
|
|
|
|
|
return "DETACH PARTITION";
|
|
|
|
|
case AT_DetachPartitionFinalize:
|
|
|
|
|
return "DETACH PARTITION ... FINALIZE";
|
|
|
|
|
case AT_AddIdentity:
|
|
|
|
|
return "ALTER COLUMN ... ADD IDENTITY";
|
|
|
|
|
case AT_SetIdentity:
|
|
|
|
|
return "ALTER COLUMN ... SET";
|
|
|
|
|
case AT_DropIdentity:
|
|
|
|
|
return "ALTER COLUMN ... DROP IDENTITY";
|
|
|
|
|
case AT_ReAddStatistics:
|
|
|
|
|
return NULL; /* not real grammar */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ATSimplePermissions
|
|
|
|
|
*
|
|
|
|
@ -5949,7 +6088,7 @@ ATGetQueueEntry(List **wqueue, Relation rel)
|
|
|
|
|
* - Ensure that it is not a system table
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
ATSimplePermissions(Relation rel, int allowed_targets)
|
|
|
|
|
ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets)
|
|
|
|
|
{
|
|
|
|
|
int actual_target;
|
|
|
|
|
|
|
|
|
@ -5984,7 +6123,21 @@ ATSimplePermissions(Relation rel, int allowed_targets)
|
|
|
|
|
|
|
|
|
|
/* Wrong target type? */
|
|
|
|
|
if ((actual_target & allowed_targets) == 0)
|
|
|
|
|
ATWrongRelkindError(rel, allowed_targets);
|
|
|
|
|
{
|
|
|
|
|
const char *action_str = alter_table_type_to_string(cmdtype);
|
|
|
|
|
|
|
|
|
|
if (action_str)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
/* translator: %s is a group of some SQL keywords */
|
|
|
|
|
errmsg("ALTER action %s cannot be performed on relation \"%s\"",
|
|
|
|
|
action_str, RelationGetRelationName(rel)),
|
|
|
|
|
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
|
|
|
|
else
|
|
|
|
|
/* internal error? */
|
|
|
|
|
elog(ERROR, "invalid ALTER action attempted on relation \"%s\"",
|
|
|
|
|
RelationGetRelationName(rel));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Permissions checks */
|
|
|
|
|
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
|
|
|
|
@ -5998,66 +6151,6 @@ ATSimplePermissions(Relation rel, int allowed_targets)
|
|
|
|
|
RelationGetRelationName(rel))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ATWrongRelkindError
|
|
|
|
|
*
|
|
|
|
|
* Throw an error when a relation has been determined to be of the wrong
|
|
|
|
|
* type.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
ATWrongRelkindError(Relation rel, int allowed_targets)
|
|
|
|
|
{
|
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
|
|
switch (allowed_targets)
|
|
|
|
|
{
|
|
|
|
|
case ATT_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a table");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_VIEW:
|
|
|
|
|
msg = _("\"%s\" is not a table or view");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a table, view, or foreign table");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX:
|
|
|
|
|
msg = _("\"%s\" is not a table, view, materialized view, or index");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_MATVIEW:
|
|
|
|
|
msg = _("\"%s\" is not a table or materialized view");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_MATVIEW | ATT_INDEX:
|
|
|
|
|
msg = _("\"%s\" is not a table, materialized view, or index");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a table, materialized view, or foreign table");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_FOREIGN_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a table or foreign table");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a table, composite type, or foreign table");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a table, materialized view, index, or foreign table");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_VIEW:
|
|
|
|
|
msg = _("\"%s\" is not a view");
|
|
|
|
|
break;
|
|
|
|
|
case ATT_FOREIGN_TABLE:
|
|
|
|
|
msg = _("\"%s\" is not a foreign table");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* shouldn't get here, add all necessary cases above */
|
|
|
|
|
msg = _("\"%s\" is of the wrong type");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg(msg, RelationGetRelationName(rel))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ATSimpleRecursion
|
|
|
|
|
*
|
|
|
|
@ -6452,7 +6545,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|
|
|
|
|
|
|
|
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
|
|
|
|
if (recursing)
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions((*cmd)->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
|
|
|
|
|
if (rel->rd_rel->relispartition && !recursing)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
@ -8186,7 +8279,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
|
|
|
|
|
|
|
|
|
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
|
|
|
|
if (recursing)
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(AT_DropColumn, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
|
|
|
|
|
/* Initialize addrs on the first invocation */
|
|
|
|
|
Assert(!recursing || addrs != NULL);
|
|
|
|
@ -8670,7 +8763,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|
|
|
|
|
|
|
|
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
|
|
|
|
if (recursing)
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(AT_AddConstraint, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Call AddRelationNewConstraints to do the work, making sure it works on
|
|
|
|
@ -11286,7 +11379,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
|
|
|
|
|
|
|
|
|
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
|
|
|
|
if (recursing)
|
|
|
|
|
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(AT_DropConstraint, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
|
|
|
|
|
conrel = table_open(ConstraintRelationId, RowExclusiveLock);
|
|
|
|
|
|
|
|
|
@ -13205,8 +13298,9 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
|
|
|
|
|
default:
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("\"%s\" is not a table, view, sequence, or foreign table",
|
|
|
|
|
NameStr(tuple_class->relname))));
|
|
|
|
|
errmsg("cannot change owner of relation \"%s\"",
|
|
|
|
|
NameStr(tuple_class->relname)),
|
|
|
|
|
errdetail_relkind_not_supported(tuple_class->relkind)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -13621,8 +13715,9 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
|
|
|
|
|
default:
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("\"%s\" is not a table, view, materialized view, index, or TOAST table",
|
|
|
|
|
RelationGetRelationName(rel))));
|
|
|
|
|
errmsg("cannot set options for relation \"%s\"",
|
|
|
|
|
RelationGetRelationName(rel)),
|
|
|
|
|
errdetail_relkind_not_supported(rel->rd_rel->relkind)));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -14176,7 +14271,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
|
|
|
|
|
* Must be owner of both parent and child -- child was checked by
|
|
|
|
|
* ATSimplePermissions call in ATPrepCmd
|
|
|
|
|
*/
|
|
|
|
|
ATSimplePermissions(parent_rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(AT_AddInherit, parent_rel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
|
|
|
|
|
/* Permanent rels cannot inherit from temporary ones */
|
|
|
|
|
if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
|
|
|
|
@ -16505,17 +16600,27 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
|
|
|
|
|
* Don't allow ALTER TABLE .. SET SCHEMA on relations that can't be moved
|
|
|
|
|
* to a different schema, such as indexes and TOAST tables.
|
|
|
|
|
*/
|
|
|
|
|
if (IsA(stmt, AlterObjectSchemaStmt) &&
|
|
|
|
|
relkind != RELKIND_RELATION &&
|
|
|
|
|
relkind != RELKIND_VIEW &&
|
|
|
|
|
relkind != RELKIND_MATVIEW &&
|
|
|
|
|
relkind != RELKIND_SEQUENCE &&
|
|
|
|
|
relkind != RELKIND_FOREIGN_TABLE &&
|
|
|
|
|
relkind != RELKIND_PARTITIONED_TABLE)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table",
|
|
|
|
|
rv->relname)));
|
|
|
|
|
if (IsA(stmt, AlterObjectSchemaStmt))
|
|
|
|
|
{
|
|
|
|
|
if (relkind == RELKIND_INDEX || relkind == RELKIND_PARTITIONED_INDEX)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("cannot change schema of index \"%s\"",
|
|
|
|
|
rv->relname),
|
|
|
|
|
errhint("Change the schema of the table instead.")));
|
|
|
|
|
else if (relkind == RELKIND_COMPOSITE_TYPE)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("cannot change schema of composite type \"%s\"",
|
|
|
|
|
rv->relname),
|
|
|
|
|
errhint("Use ALTER TYPE instead.")));
|
|
|
|
|
else if (relkind == RELKIND_TOASTVALUE)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
|
errmsg("cannot change schema of TOAST table \"%s\"",
|
|
|
|
|
rv->relname),
|
|
|
|
|
errhint("Change the schema of the table instead.")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReleaseSysCache(tuple);
|
|
|
|
|
}
|
|
|
|
@ -17077,7 +17182,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd,
|
|
|
|
|
* Must be owner of both parent and source table -- parent was checked by
|
|
|
|
|
* ATSimplePermissions call in ATPrepCmd
|
|
|
|
|
*/
|
|
|
|
|
ATSimplePermissions(attachrel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
ATSimplePermissions(AT_AttachPartition, attachrel, ATT_TABLE | ATT_FOREIGN_TABLE);
|
|
|
|
|
|
|
|
|
|
/* A partition can only have one parent */
|
|
|
|
|
if (attachrel->rd_rel->relispartition)
|
|
|
|
|