diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/tablecmds.c | 419 |
1 files changed, 309 insertions, 110 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 32e19c5e4fc..002319e8a02 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -282,9 +282,9 @@ static void AlterIndexNamespaces(Relation classRel, Relation rel, static void AlterSeqNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved, LOCKMODE lockmode); -static void ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, +static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing, LOCKMODE lockmode); -static void ATExecValidateConstraint(Relation rel, char *constrName, +static ObjectAddress ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, bool recursing, LOCKMODE lockmode); static int transformColumnNameList(Oid relId, List *colList, int16 *attnums, Oid *atttypids); @@ -326,47 +326,47 @@ static List *find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior behavior); static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing, bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode); -static void ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, - ColumnDef *colDef, bool isOid, +static ObjectAddress ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, + Relation rel, ColumnDef *colDef, bool isOid, bool recurse, bool recursing, LOCKMODE lockmode); static void check_for_column_name_collision(Relation rel, const char *colname); static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid); static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid); static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOCKMODE lockmode); -static void ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode); -static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, +static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode); +static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, const char *colName, LOCKMODE lockmode); -static void ATExecColumnDefault(Relation rel, const char *colName, +static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName, Node *newDefault, LOCKMODE lockmode); static void ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode); -static void ATExecSetStatistics(Relation rel, const char *colName, +static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode); -static void ATExecSetOptions(Relation rel, const char *colName, +static ObjectAddress ATExecSetOptions(Relation rel, const char *colName, Node *options, bool isReset, LOCKMODE lockmode); -static void ATExecSetStorage(Relation rel, const char *colName, +static ObjectAddress ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode); static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing, AlterTableCmd *cmd, LOCKMODE lockmode); -static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName, +static ObjectAddress ATExecDropColumn(List **wqueue, Relation rel, const char *colName, DropBehavior behavior, bool recurse, bool recursing, bool missing_ok, LOCKMODE lockmode); -static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel, +static ObjectAddress ATExecAddIndex(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode); -static void ATExecAddConstraint(List **wqueue, +static ObjectAddress ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *newConstraint, bool recurse, bool is_readd, LOCKMODE lockmode); -static void ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, +static ObjectAddress ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, LOCKMODE lockmode); -static void ATAddCheckConstraint(List **wqueue, +static ObjectAddress ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *constr, bool recurse, bool recursing, bool is_readd, LOCKMODE lockmode); -static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, +static ObjectAddress ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, Constraint *fkconstraint, LOCKMODE lockmode); static void ATExecDropConstraint(Relation rel, const char *constrName, DropBehavior behavior, @@ -377,9 +377,9 @@ static void ATPrepAlterColumnType(List **wqueue, bool recurse, bool recursing, AlterTableCmd *cmd, LOCKMODE lockmode); static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno); -static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, +static ObjectAddress ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd, LOCKMODE lockmode); -static void ATExecAlterColumnGenericOptions(Relation rel, const char *colName, +static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName, List *options, LOCKMODE lockmode); static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode); @@ -392,7 +392,7 @@ static void change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId); static void change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode); -static void ATExecClusterOn(Relation rel, const char *indexName, +static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode); static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static bool ATPrepChangePersistence(Relation rel, bool toLogged); @@ -407,10 +407,10 @@ static void ATExecEnableDisableTrigger(Relation rel, char *trigname, static void ATExecEnableDisableRule(Relation rel, char *rulename, char fires_when, LOCKMODE lockmode); static void ATPrepAddInherit(Relation child_rel); -static void ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode); -static void ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode); +static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode); +static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode); static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid); -static void ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode); +static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode); static void ATExecDropOf(Relation rel, LOCKMODE lockmode); static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode); static void ATExecGenericOptions(Relation rel, List *options); @@ -623,6 +623,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked->contype = CONSTR_DEFAULT; + cooked->conoid = InvalidOid; /* until created */ cooked->name = NULL; cooked->attnum = attnum; cooked->expr = colDef->cooked_default; @@ -1742,6 +1743,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked->contype = CONSTR_CHECK; + cooked->conoid = InvalidOid; /* until created */ cooked->name = pstrdup(name); cooked->attnum = 0; /* not used for constraints */ cooked->expr = expr; @@ -3429,78 +3431,90 @@ static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd, LOCKMODE lockmode) { + ObjectAddress address = InvalidObjectAddress; + switch (cmd->subtype) { case AT_AddColumn: /* ADD COLUMN */ case AT_AddColumnToView: /* add column via CREATE OR REPLACE * VIEW */ - ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, - false, false, false, lockmode); + address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, + false, false, false, lockmode); break; case AT_AddColumnRecurse: - ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, - false, true, false, lockmode); + address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, + false, true, false, lockmode); break; case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */ - ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode); + address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode); break; case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */ - ATExecDropNotNull(rel, cmd->name, lockmode); + address = ATExecDropNotNull(rel, cmd->name, lockmode); break; case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ - ATExecSetNotNull(tab, rel, cmd->name, lockmode); + address = ATExecSetNotNull(tab, rel, cmd->name, lockmode); break; case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */ - ATExecSetStatistics(rel, cmd->name, cmd->def, lockmode); + address = ATExecSetStatistics(rel, cmd->name, cmd->def, lockmode); break; case AT_SetOptions: /* ALTER COLUMN SET ( options ) */ - ATExecSetOptions(rel, cmd->name, cmd->def, false, lockmode); + address = ATExecSetOptions(rel, cmd->name, cmd->def, false, lockmode); break; case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */ - ATExecSetOptions(rel, cmd->name, cmd->def, true, lockmode); + address = ATExecSetOptions(rel, cmd->name, cmd->def, true, lockmode); break; case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ - ATExecSetStorage(rel, cmd->name, cmd->def, lockmode); + address = ATExecSetStorage(rel, cmd->name, cmd->def, lockmode); break; case AT_DropColumn: /* DROP COLUMN */ - ATExecDropColumn(wqueue, rel, cmd->name, - cmd->behavior, false, false, cmd->missing_ok, lockmode); + address = ATExecDropColumn(wqueue, rel, cmd->name, + cmd->behavior, false, false, + cmd->missing_ok, lockmode); break; case AT_DropColumnRecurse: /* DROP COLUMN with recursion */ - ATExecDropColumn(wqueue, rel, cmd->name, - cmd->behavior, true, false, cmd->missing_ok, lockmode); + address = ATExecDropColumn(wqueue, rel, cmd->name, + cmd->behavior, true, false, + cmd->missing_ok, lockmode); break; case AT_AddIndex: /* ADD INDEX */ - ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false, lockmode); + address = ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false, + lockmode); break; case AT_ReAddIndex: /* ADD INDEX */ - ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true, lockmode); + address = ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true, + lockmode); break; case AT_AddConstraint: /* ADD CONSTRAINT */ - ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, - false, false, lockmode); + address = + ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, + false, false, lockmode); break; case AT_AddConstraintRecurse: /* ADD CONSTRAINT with recursion */ - ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, - true, false, lockmode); + address = + ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, + true, false, lockmode); break; case AT_ReAddConstraint: /* Re-add pre-existing check * constraint */ - ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, - false, true, lockmode); + address = + ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, + false, true, lockmode); break; case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */ - ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def, lockmode); + address = ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def, + lockmode); break; case AT_AlterConstraint: /* ALTER CONSTRAINT */ - ATExecAlterConstraint(rel, cmd, false, false, lockmode); + address = ATExecAlterConstraint(rel, cmd, false, false, lockmode); break; case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */ - ATExecValidateConstraint(rel, cmd->name, false, false, lockmode); + address = ATExecValidateConstraint(rel, cmd->name, false, false, + lockmode); break; case AT_ValidateConstraintRecurse: /* VALIDATE CONSTRAINT with * recursion */ - ATExecValidateConstraint(rel, cmd->name, true, false, lockmode); + address = ATExecValidateConstraint(rel, cmd->name, true, false, + lockmode); break; case AT_DropConstraint: /* DROP CONSTRAINT */ ATExecDropConstraint(rel, cmd->name, cmd->behavior, @@ -3513,10 +3527,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, cmd->missing_ok, lockmode); break; case AT_AlterColumnType: /* ALTER COLUMN TYPE */ - ATExecAlterColumnType(tab, rel, cmd, lockmode); + address = ATExecAlterColumnType(tab, rel, cmd, lockmode); break; case AT_AlterColumnGenericOptions: /* ALTER COLUMN OPTIONS */ - ATExecAlterColumnGenericOptions(rel, cmd->name, (List *) cmd->def, lockmode); + address = + ATExecAlterColumnGenericOptions(rel, cmd->name, + (List *) cmd->def, lockmode); break; case AT_ChangeOwner: /* ALTER OWNER */ ATExecChangeOwner(RelationGetRelid(rel), @@ -3524,7 +3540,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, false, lockmode); break; case AT_ClusterOn: /* CLUSTER ON */ - ATExecClusterOn(rel, cmd->name, lockmode); + address = ATExecClusterOn(rel, cmd->name, lockmode); break; case AT_DropCluster: /* SET WITHOUT CLUSTER */ ATExecDropCluster(rel, lockmode); @@ -3535,14 +3551,16 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, case AT_AddOids: /* SET WITH OIDS */ /* Use the ADD COLUMN code, unless prep decided to do nothing */ if (cmd->def != NULL) - ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, - true, false, false, lockmode); + address = + ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, + true, false, false, lockmode); break; case AT_AddOidsRecurse: /* SET WITH OIDS */ /* Use the ADD COLUMN code, unless prep decided to do nothing */ if (cmd->def != NULL) - ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, - true, true, false, lockmode); + address = + ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, + true, true, false, lockmode); break; case AT_DropOids: /* SET WITHOUT OIDS */ @@ -3613,13 +3631,13 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, break; case AT_AddInherit: - ATExecAddInherit(rel, (RangeVar *) cmd->def, lockmode); + address = ATExecAddInherit(rel, (RangeVar *) cmd->def, lockmode); break; case AT_DropInherit: - ATExecDropInherit(rel, (RangeVar *) cmd->def, lockmode); + address = ATExecDropInherit(rel, (RangeVar *) cmd->def, lockmode); break; case AT_AddOf: - ATExecAddOf(rel, (TypeName *) cmd->def, lockmode); + address = ATExecAddOf(rel, (TypeName *) cmd->def, lockmode); break; case AT_DropOf: ATExecDropOf(rel, lockmode); @@ -3642,6 +3660,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, break; } + /* supress compiler warning until we have some use for the address */ + (void) address; + /* * Bump the command counter to ensure the next subcommand in the sequence * can see the changes so far @@ -4626,7 +4647,11 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing, cmd->subtype = AT_AddColumnRecurse; } -static void +/* + * Add a column to a table; this handles the AT_AddOids cases as well. The + * return value is the address of the new column in the parent relation. + */ +static ObjectAddress ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ColumnDef *colDef, bool isOid, bool recurse, bool recursing, LOCKMODE lockmode) @@ -4647,6 +4672,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, List *children; ListCell *child; AclResult aclresult; + ObjectAddress address; /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) @@ -4711,7 +4737,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, colDef->colname, RelationGetRelationName(rel)))); heap_close(attrdesc, RowExclusiveLock); - return; + return InvalidObjectAddress; } } @@ -4951,12 +4977,15 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, /* Find or create work queue entry for this table */ childtab = ATGetQueueEntry(wqueue, childrel); - /* Recurse to child */ + /* Recurse to child; return value is ignored */ ATExecAddColumn(wqueue, childtab, childrel, colDef, isOid, recurse, true, lockmode); heap_close(childrel, NoLock); } + + ObjectAddressSubSet(address, RelationRelationId, myrelid, newattnum); + return address; } /* @@ -5070,8 +5099,11 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC /* * ALTER TABLE ALTER COLUMN DROP NOT NULL + * + * Return the address of the modified column. If the column was already + * nullable, InvalidObjectAddress is returned. */ -static void +static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) { HeapTuple tuple; @@ -5079,6 +5111,7 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) Relation attr_rel; List *indexoidlist; ListCell *indexoidscan; + ObjectAddress address; /* * lookup the attribute @@ -5156,24 +5189,35 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) /* keep the system catalog indexes current */ CatalogUpdateIndexes(attr_rel, tuple); + + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); } + else + address = InvalidObjectAddress; InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attnum); heap_close(attr_rel, RowExclusiveLock); + + return address; } /* * ALTER TABLE ALTER COLUMN SET NOT NULL + * + * Return the address of the modified column. If the column was already NOT + * NULL, InvalidObjectAddress is returned. */ -static void +static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, const char *colName, LOCKMODE lockmode) { HeapTuple tuple; AttrNumber attnum; Relation attr_rel; + ObjectAddress address; /* * lookup the attribute @@ -5211,22 +5255,32 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, /* Tell Phase 3 it needs to test the constraint */ tab->new_notnull = true; + + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); } + else + address = InvalidObjectAddress; InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attnum); heap_close(attr_rel, RowExclusiveLock); + + return address; } /* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT + * + * Return the address of the affected column. */ -static void +static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName, Node *newDefault, LOCKMODE lockmode) { AttrNumber attnum; + ObjectAddress address; /* * get the number of the attribute @@ -5273,6 +5327,10 @@ ATExecColumnDefault(Relation rel, const char *colName, AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true, false); } + + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); + return address; } /* @@ -5302,13 +5360,18 @@ ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE RelationGetRelationName(rel)); } -static void +/* + * Return value is the address of the modified column + */ +static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode) { int newtarget; Relation attrelation; HeapTuple tuple; Form_pg_attribute attrtuple; + AttrNumber attnum; + ObjectAddress address; Assert(IsA(newValue, Integer)); newtarget = intVal(newValue); @@ -5343,7 +5406,8 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE colName, RelationGetRelationName(rel)))); attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); - if (attrtuple->attnum <= 0) + attnum = attrtuple->attnum; + if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", @@ -5359,12 +5423,19 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attrtuple->attnum); + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); heap_freetuple(tuple); heap_close(attrelation, RowExclusiveLock); + + return address; } -static void +/* + * Return value is the address of the modified column + */ +static ObjectAddress ATExecSetOptions(Relation rel, const char *colName, Node *options, bool isReset, LOCKMODE lockmode) { @@ -5372,9 +5443,11 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, HeapTuple tuple, newtuple; Form_pg_attribute attrtuple; + AttrNumber attnum; Datum datum, newOptions; bool isnull; + ObjectAddress address; Datum repl_val[Natts_pg_attribute]; bool repl_null[Natts_pg_attribute]; bool repl_repl[Natts_pg_attribute]; @@ -5390,7 +5463,8 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, colName, RelationGetRelationName(rel)))); attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); - if (attrtuple->attnum <= 0) + attnum = attrtuple->attnum; + if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", @@ -5424,17 +5498,24 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attrtuple->attnum); + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); + heap_freetuple(newtuple); ReleaseSysCache(tuple); heap_close(attrelation, RowExclusiveLock); + + return address; } /* * ALTER TABLE ALTER COLUMN SET STORAGE + * + * Return value is the address of the modified column */ -static void +static ObjectAddress ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode) { char *storagemode; @@ -5442,6 +5523,8 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc Relation attrelation; HeapTuple tuple; Form_pg_attribute attrtuple; + AttrNumber attnum; + ObjectAddress address; Assert(IsA(newValue, String)); storagemode = strVal(newValue); @@ -5474,7 +5557,8 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc colName, RelationGetRelationName(rel)))); attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); - if (attrtuple->attnum <= 0) + attnum = attrtuple->attnum; + if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", @@ -5504,6 +5588,10 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc heap_freetuple(tuple); heap_close(attrelation, RowExclusiveLock); + + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); + return address; } @@ -5532,7 +5620,10 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing, cmd->subtype = AT_DropColumnRecurse; } -static void +/* + * Return value is that of the dropped column. + */ +static ObjectAddress ATExecDropColumn(List **wqueue, Relation rel, const char *colName, DropBehavior behavior, bool recurse, bool recursing, @@ -5566,7 +5657,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, ereport(NOTICE, (errmsg("column \"%s\" of relation \"%s\" does not exist, skipping", colName, RelationGetRelationName(rel)))); - return; + return InvalidObjectAddress; } } targetatt = (Form_pg_attribute) GETSTRUCT(tuple); @@ -5720,6 +5811,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, /* Tell Phase 3 to physically remove the OID column */ tab->rewrite |= AT_REWRITE_ALTER_OID; } + + return object; } /* @@ -5728,8 +5821,10 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, * There is no such command in the grammar, but parse_utilcmd.c converts * UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands. This lets * us schedule creation of the index at the appropriate time during ALTER. + * + * Return value is the address of the new index. */ -static void +static ObjectAddress ATExecAddIndex(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode) { @@ -5772,12 +5867,16 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel, RelationPreserveStorage(irel->rd_node, true); index_close(irel, NoLock); } + + return address; } /* * ALTER TABLE ADD CONSTRAINT USING INDEX + * + * Returns the address of the new constraint. */ -static void +static ObjectAddress ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, LOCKMODE lockmode) { @@ -5787,6 +5886,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, IndexInfo *indexInfo; char *constraintName; char constraintType; + ObjectAddress address; Assert(IsA(stmt, IndexStmt)); Assert(OidIsValid(index_oid)); @@ -5831,30 +5931,37 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, constraintType = CONSTRAINT_UNIQUE; /* Create the catalog entries for the constraint */ - index_constraint_create(rel, - index_oid, - indexInfo, - constraintName, - constraintType, - stmt->deferrable, - stmt->initdeferred, - stmt->primary, - true, /* update pg_index */ - true, /* remove old dependencies */ - allowSystemTableMods, - false); /* is_internal */ + address = index_constraint_create(rel, + index_oid, + indexInfo, + constraintName, + constraintType, + stmt->deferrable, + stmt->initdeferred, + stmt->primary, + true, /* update pg_index */ + true, /* remove old dependencies */ + allowSystemTableMods, + false); /* is_internal */ index_close(indexRel, NoLock); + + return address; } /* * ALTER TABLE ADD CONSTRAINT + * + * Return value is the address of the new constraint; if no constraint was + * added, InvalidObjectAddress is returned. */ -static void +static ObjectAddress ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *newConstraint, bool recurse, bool is_readd, LOCKMODE lockmode) { + ObjectAddress address = InvalidObjectAddress; + Assert(IsA(newConstraint, Constraint)); /* @@ -5865,9 +5972,10 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, switch (newConstraint->contype) { case CONSTR_CHECK: - ATAddCheckConstraint(wqueue, tab, rel, - newConstraint, recurse, false, is_readd, - lockmode); + address = + ATAddCheckConstraint(wqueue, tab, rel, + newConstraint, recurse, false, is_readd, + lockmode); break; case CONSTR_FOREIGN: @@ -5898,17 +6006,22 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, RelationGetNamespace(rel), NIL); - ATAddForeignKeyConstraint(tab, rel, newConstraint, lockmode); + address = ATAddForeignKeyConstraint(tab, rel, newConstraint, + lockmode); break; default: elog(ERROR, "unrecognized constraint type: %d", (int) newConstraint->contype); } + + return address; } /* - * Add a check constraint to a single table and its children + * Add a check constraint to a single table and its children. Returns the + * address of the constraint added to the parent relation, if one gets added, + * or InvalidObjectAddress otherwise. * * Subroutine for ATExecAddConstraint. * @@ -5927,7 +6040,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * "is_readd" flag for that; just setting recurse=false would result in an * error if there are child tables. */ -static void +static ObjectAddress ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *constr, bool recurse, bool recursing, bool is_readd, LOCKMODE lockmode) @@ -5936,6 +6049,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ListCell *lcon; List *children; ListCell *child; + ObjectAddress address = InvalidObjectAddress; /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) @@ -5957,6 +6071,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, !recursing, /* is_local */ is_readd); /* is_internal */ + /* we don't expect more than one constraint here */ + Assert(list_length(newcons) <= 1); + /* Add each to-be-validated constraint to Phase 3's queue */ foreach(lcon, newcons) { @@ -5978,6 +6095,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, /* Save the actually assigned name if it was defaulted */ if (constr->conname == NULL) constr->conname = ccon->name; + + ObjectAddressSet(address, ConstraintRelationId, ccon->conoid); } /* At this point we must have a locked-down name to use */ @@ -5993,7 +6112,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * incorrect value for coninhcount. */ if (newcons == NIL) - return; + return address; /* * If adding a NO INHERIT constraint, no need to find our children. @@ -6001,7 +6120,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * handled at higher levels). */ if (constr->is_no_inherit || is_readd) - return; + return address; /* * Propagate to children as appropriate. Unlike most other ALTER @@ -6039,16 +6158,19 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, heap_close(childrel, NoLock); } + + return address; } /* - * Add a foreign-key constraint to a single table + * Add a foreign-key constraint to a single table; return the new constraint's + * address. * * Subroutine for ATExecAddConstraint. Must already hold exclusive * lock on the rel, and have done appropriate validity checks for it. * We do permissions checks here, however. */ -static void +static ObjectAddress ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, Constraint *fkconstraint, LOCKMODE lockmode) { @@ -6067,6 +6189,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, Oid indexOid; Oid constrOid; bool old_check_ok; + ObjectAddress address; ListCell *old_pfeqop_item = list_head(fkconstraint->old_conpfeqop); /* @@ -6414,6 +6537,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, 0, /* inhcount */ true, /* isnoinherit */ false); /* is_internal */ + ObjectAddressSet(address, ConstraintRelationId, constrOid); /* * Create the triggers that will enforce the constraint. @@ -6447,6 +6571,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, * Close pk table, but keep lock until we've committed. */ heap_close(pkrel, NoLock); + + return address; } /* @@ -6458,8 +6584,11 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, * Foreign keys do not inherit, so we purposely ignore the * recursion bit here, but we keep the API the same for when * other constraint types are supported. + * + * If the constraint is modified, returns its address; otherwise, return + * InvalidObjectAddress. */ -static void +static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing, LOCKMODE lockmode) { @@ -6470,6 +6599,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, Form_pg_constraint currcon = NULL; Constraint *cmdcon = NULL; bool found = false; + ObjectAddress address; Assert(IsA(cmd->def, Constraint)); cmdcon = (Constraint *) cmd->def; @@ -6571,11 +6701,18 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, * Invalidate relcache so that others see the new attributes. */ CacheInvalidateRelcache(rel); + + ObjectAddressSet(address, ConstraintRelationId, + HeapTupleGetOid(contuple)); } + else + address = InvalidObjectAddress; systable_endscan(scan); heap_close(conrel, RowExclusiveLock); + + return address; } /* @@ -6585,8 +6722,11 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, * there's no good way to skip recursing when handling foreign keys: there is * no need to lock children in that case, yet we wouldn't be able to avoid * doing so at that level. + * + * Return value is the address of the validated constraint. If the constraint + * was already validated, InvalidObjectAddress is returned. */ -static void +static ObjectAddress ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, bool recursing, LOCKMODE lockmode) { @@ -6596,6 +6736,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, HeapTuple tuple; Form_pg_constraint con = NULL; bool found = false; + ObjectAddress address; conrel = heap_open(ConstraintRelationId, RowExclusiveLock); @@ -6639,7 +6780,6 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, if (con->contype == CONSTRAINT_FOREIGN) { - Oid conid = HeapTupleGetOid(tuple); Relation refrel; /* @@ -6654,7 +6794,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, validateForeignKeyConstraint(constrName, rel, refrel, con->conindid, - conid); + HeapTupleGetOid(tuple)); heap_close(refrel, NoLock); /* @@ -6730,11 +6870,18 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, HeapTupleGetOid(tuple), 0); heap_freetuple(copyTuple); + + ObjectAddressSet(address, ConstraintRelationId, + HeapTupleGetOid(tuple)); } + else + address = InvalidObjectAddress; /* already validated */ systable_endscan(scan); heap_close(conrel, RowExclusiveLock); + + return address; } @@ -7825,7 +7972,12 @@ ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno) } } -static void +/* + * ALTER COLUMN .. SET DATA TYPE + * + * Return the address of the modified column. + */ +static ObjectAddress ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd, LOCKMODE lockmode) { @@ -7846,6 +7998,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, ScanKeyData key[3]; SysScanDesc scan; HeapTuple depTup; + ObjectAddress address; attrelation = heap_open(AttributeRelationId, RowExclusiveLock); @@ -8217,11 +8370,19 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, StoreAttrDefault(rel, attnum, defaultexpr, true); } + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); + /* Cleanup */ heap_freetuple(heapTup); + + return address; } -static void +/* + * Returns the address of the modified column + */ +static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName, List *options, @@ -8240,9 +8401,11 @@ ATExecAlterColumnGenericOptions(Relation rel, Datum datum; Form_pg_foreign_table fttableform; Form_pg_attribute atttableform; + AttrNumber attnum; + ObjectAddress address; if (options == NIL) - return; + return InvalidObjectAddress; /* First, determine FDW validator associated to the foreign table. */ ftrel = heap_open(ForeignTableRelationId, AccessShareLock); @@ -8269,7 +8432,8 @@ ATExecAlterColumnGenericOptions(Relation rel, /* Prevent them from altering a system attribute */ atttableform = (Form_pg_attribute) GETSTRUCT(tuple); - if (atttableform->attnum <= 0) + attnum = atttableform->attnum; + if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", colName))); @@ -8312,12 +8476,16 @@ ATExecAlterColumnGenericOptions(Relation rel, InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), atttableform->attnum); + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); ReleaseSysCache(tuple); heap_close(attrel, RowExclusiveLock); heap_freetuple(newtuple); + + return address; } /* @@ -8958,11 +9126,14 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lock * ALTER TABLE CLUSTER ON * * The only thing we have to do is to change the indisclustered bits. + * + * Return the address of the new clustering index. */ -static void +static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode) { Oid indexOid; + ObjectAddress address; indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace); @@ -8977,6 +9148,11 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode) /* And do the work */ mark_index_clustered(rel, indexOid, false); + + ObjectAddressSet(address, + RelationRelationId, indexOid); + + return address; } /* @@ -9677,7 +9853,10 @@ ATPrepAddInherit(Relation child_rel) errmsg("cannot change inheritance of typed table"))); } -static void +/* + * Return the address of the new parent relation. + */ +static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) { Relation parent_rel, @@ -9687,6 +9866,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) HeapTuple inheritsTuple; int32 inhseqno; List *children; + ObjectAddress address; /* * A self-exclusive lock is needed here. See the similar case in @@ -9801,11 +9981,16 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) inhseqno + 1, catalogRelation); + ObjectAddressSet(address, RelationRelationId, + RelationGetRelid(parent_rel)); + /* Now we're done with pg_inherits */ heap_close(catalogRelation, RowExclusiveLock); /* keep our lock on the parent relation until commit */ heap_close(parent_rel, NoLock); + + return address; } /* @@ -10073,11 +10258,14 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) * * coninhcount and conislocal for inherited constraints are adjusted in * exactly the same way. + * + * Return value is the OID of the relation that is no longer parent. */ -static void +static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) { Relation parent_rel; + Oid parent_oid; Relation catalogRelation; SysScanDesc scan; ScanKeyData key[3]; @@ -10086,6 +10274,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) constraintTuple; List *connames; bool found = false; + ObjectAddress address; /* * AccessShareLock on the parent is probably enough, seeing that DROP @@ -10246,6 +10435,8 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) } } + parent_oid = RelationGetRelid(parent_rel); + systable_endscan(scan); heap_close(catalogRelation, RowExclusiveLock); @@ -10264,6 +10455,10 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) /* keep our lock on the parent relation until commit */ heap_close(parent_rel, NoLock); + + ObjectAddressSet(address, RelationRelationId, parent_oid); + + return address; } /* @@ -10321,8 +10516,10 @@ drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid) * TABLE OF. All attname, atttypid, atttypmod and attcollation must match. The * subject table must not have inheritance parents. These restrictions ensure * that you cannot create a configuration impossible with CREATE TABLE OF alone. + * + * The address of the type is returned. */ -static void +static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) { Oid relid = RelationGetRelid(rel); @@ -10451,6 +10648,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) heap_close(relationRelation, RowExclusiveLock); ReleaseSysCache(typetuple); + + return typeobj; } /* |