]> granicus.if.org Git - postgresql/commitdiff
Return ObjectAddress in many ALTER TABLE sub-routines
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 25 Mar 2015 20:17:56 +0000 (17:17 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 25 Mar 2015 20:17:56 +0000 (17:17 -0300)
Since commit a2e35b53c39b2a, most CREATE and ALTER commands return the
ObjectAddress of the affected object.  This is useful for event triggers
to try to figure out exactly what happened.  This patch extends this
idea a bit further to cover ALTER TABLE as well: an auxiliary
ObjectAddress is returned for each of several subcommands of ALTER
TABLE.  This makes it possible to decode with precision what happened
during execution of any ALTER TABLE command; for instance, which
constraint was added by ALTER TABLE ADD CONSTRAINT, or which parent got
dropped from the parents list by ALTER TABLE NO INHERIT.

As with the previous patch, there is no immediate user-visible change
here.

This is all really just continuing what c504513f83a9ee8 started.

Reviewed by Stephen Frost.

src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/pg_constraint.c
src/backend/commands/tablecmds.c
src/include/catalog/heap.h
src/include/catalog/index.h

index e0dbcea0939f288be30029a97b1954277964236c..c518c50b21bfc7ae9e4109726ed9e345e16711d5 100644 (file)
@@ -97,7 +97,7 @@ static ObjectAddress AddNewRelationType(const char *typeName,
                                   Oid new_row_type,
                                   Oid new_array_type);
 static void RelationRemoveInheritance(Oid relid);
-static void StoreRelCheck(Relation rel, char *ccname, Node *expr,
+static Oid StoreRelCheck(Relation rel, char *ccname, Node *expr,
                          bool is_validated, bool is_local, int inhcount,
                          bool is_no_inherit, bool is_internal);
 static void StoreConstraints(Relation rel, List *cooked_constraints,
@@ -1852,8 +1852,10 @@ heap_drop_with_catalog(Oid relid)
 
 /*
  * Store a default expression for column attnum of relation rel.
+ *
+ * Returns the OID of the new pg_attrdef tuple.
  */
-void
+Oid
 StoreAttrDefault(Relation rel, AttrNumber attnum,
                                 Node *expr, bool is_internal)
 {
@@ -1958,6 +1960,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
         */
        InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
                                                                  RelationGetRelid(rel), attnum, is_internal);
+
+       return attrdefOid;
 }
 
 /*
@@ -1965,8 +1969,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
  *
  * Caller is responsible for updating the count of constraints
  * in the pg_class entry for the relation.
+ *
+ * The OID of the new constraint is returned.
  */
-static void
+static Oid
 StoreRelCheck(Relation rel, char *ccname, Node *expr,
                          bool is_validated, bool is_local, int inhcount,
                          bool is_no_inherit, bool is_internal)
@@ -1976,6 +1982,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
        List       *varList;
        int                     keycount;
        int16      *attNos;
+       Oid                     constrOid;
 
        /*
         * Flatten expression to string form for storage.
@@ -2027,42 +2034,47 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
        /*
         * Create the Check Constraint
         */
-       CreateConstraintEntry(ccname,           /* Constraint Name */
-                                                 RelationGetNamespace(rel),    /* namespace */
-                                                 CONSTRAINT_CHECK,             /* Constraint Type */
-                                                 false,        /* Is Deferrable */
-                                                 false,        /* Is Deferred */
-                                                 is_validated,
-                                                 RelationGetRelid(rel),                /* relation */
-                                                 attNos,               /* attrs in the constraint */
-                                                 keycount,             /* # attrs in the constraint */
-                                                 InvalidOid,   /* not a domain constraint */
-                                                 InvalidOid,   /* no associated index */
-                                                 InvalidOid,   /* Foreign key fields */
-                                                 NULL,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL,
-                                                 0,
-                                                 ' ',
-                                                 ' ',
-                                                 ' ',
-                                                 NULL, /* not an exclusion constraint */
-                                                 expr, /* Tree form of check constraint */
-                                                 ccbin,        /* Binary form of check constraint */
-                                                 ccsrc,        /* Source form of check constraint */
-                                                 is_local,             /* conislocal */
-                                                 inhcount,             /* coninhcount */
-                                                 is_no_inherit,                /* connoinherit */
-                                                 is_internal); /* internally constructed? */
+       constrOid =
+               CreateConstraintEntry(ccname,   /* Constraint Name */
+                                                         RelationGetNamespace(rel),            /* namespace */
+                                                         CONSTRAINT_CHECK, /* Constraint Type */
+                                                         false,        /* Is Deferrable */
+                                                         false,        /* Is Deferred */
+                                                         is_validated,
+                                                         RelationGetRelid(rel),        /* relation */
+                                                         attNos,       /* attrs in the constraint */
+                                                         keycount, /* # attrs in the constraint */
+                                                         InvalidOid,           /* not a domain constraint */
+                                                         InvalidOid,           /* no associated index */
+                                                         InvalidOid,           /* Foreign key fields */
+                                                         NULL,
+                                                         NULL,
+                                                         NULL,
+                                                         NULL,
+                                                         0,
+                                                         ' ',
+                                                         ' ',
+                                                         ' ',
+                                                         NULL,         /* not an exclusion constraint */
+                                                         expr,         /* Tree form of check constraint */
+                                                         ccbin,        /* Binary form of check constraint */
+                                                         ccsrc,        /* Source form of check constraint */
+                                                         is_local, /* conislocal */
+                                                         inhcount, /* coninhcount */
+                                                         is_no_inherit,        /* connoinherit */
+                                                         is_internal);         /* internally constructed? */
 
        pfree(ccbin);
        pfree(ccsrc);
+
+       return constrOid;
 }
 
 /*
  * Store defaults and constraints (passed as a list of CookedConstraint).
  *
+ * Each CookedConstraint struct is modified to store the new catalog tuple OID.
+ *
  * NOTE: only pre-cooked expressions will be passed this way, which is to
  * say expressions inherited from an existing relation.  Newly parsed
  * expressions can be added later, by direct calls to StoreAttrDefault
@@ -2074,7 +2086,7 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
        int                     numchecks = 0;
        ListCell   *lc;
 
-       if (!cooked_constraints)
+       if (cooked_constraints == NIL)
                return;                                 /* nothing to do */
 
        /*
@@ -2091,12 +2103,15 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
                switch (con->contype)
                {
                        case CONSTR_DEFAULT:
-                               StoreAttrDefault(rel, con->attnum, con->expr, is_internal);
+                               con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
+                                                                                          is_internal);
                                break;
                        case CONSTR_CHECK:
-                               StoreRelCheck(rel, con->name, con->expr, !con->skip_validation,
-                                                         con->is_local, con->inhcount,
-                                                         con->is_no_inherit, is_internal);
+                               con->conoid =
+                                       StoreRelCheck(rel, con->name, con->expr,
+                                                                 !con->skip_validation, con->is_local,
+                                                                 con->inhcount, con->is_no_inherit,
+                                                                 is_internal);
                                numchecks++;
                                break;
                        default:
@@ -2184,6 +2199,7 @@ AddRelationNewConstraints(Relation rel,
        {
                RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
                Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
+               Oid                     defOid;
 
                expr = cookDefault(pstate, colDef->raw_default,
                                                   atp->atttypid, atp->atttypmod,
@@ -2204,10 +2220,11 @@ AddRelationNewConstraints(Relation rel,
                        (IsA(expr, Const) &&((Const *) expr)->constisnull))
                        continue;
 
-               StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
+               defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
 
                cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
                cooked->contype = CONSTR_DEFAULT;
+               cooked->conoid = defOid;
                cooked->name = NULL;
                cooked->attnum = colDef->attnum;
                cooked->expr = expr;
@@ -2227,6 +2244,7 @@ AddRelationNewConstraints(Relation rel,
        {
                Constraint *cdef = (Constraint *) lfirst(cell);
                char       *ccname;
+               Oid                     constrOid;
 
                if (cdef->contype != CONSTR_CHECK)
                        continue;
@@ -2329,13 +2347,15 @@ AddRelationNewConstraints(Relation rel,
                /*
                 * OK, store it.
                 */
-               StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
-                                         is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
+               constrOid =
+                       StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
+                                                 is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
 
                numchecks++;
 
                cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
                cooked->contype = CONSTR_CHECK;
+               cooked->conoid = constrOid;
                cooked->name = ccname;
                cooked->attnum = 0;
                cooked->expr = expr;
index f85ed93e401153ab94b8164b000fd0c0eedf8d97..351dcb27847074569562f01ffed15e92651ca71d 100644 (file)
@@ -675,7 +675,7 @@ UpdateIndexRelation(Oid indexoid,
  *             to fix it up.
  * is_internal: if true, post creation hook for new index
  * if_not_exists: if true, do not throw an error if a relation with
- *     the same name already exists.
+ *             the same name already exists.
  *
  * Returns the OID of the created index.
  */
@@ -1111,7 +1111,8 @@ index_create(Relation heapRelation,
 /*
  * index_constraint_create
  *
- * Set up a constraint associated with an index
+ * Set up a constraint associated with an index.  Return the new constraint's
+ * address.
  *
  * heapRelation: table owning the index (must be suitably locked by caller)
  * indexRelationId: OID of the index
@@ -1128,7 +1129,7 @@ index_create(Relation heapRelation,
  * allow_system_table_mods: allow table to be a system catalog
  * is_internal: index is constructed due to internal process
  */
-void
+ObjectAddress
 index_constraint_create(Relation heapRelation,
                                                Oid indexRelationId,
                                                IndexInfo *indexInfo,
@@ -1316,6 +1317,8 @@ index_constraint_create(Relation heapRelation,
                heap_freetuple(indexTuple);
                heap_close(pg_index, RowExclusiveLock);
        }
+
+       return referenced;
 }
 
 /*
index 77fe91858da413a9a1f931d1e728f9285ab7b92b..3c756f82278abea7eaf94820ef2486e3bcf80d37 100644 (file)
@@ -40,6 +40,8 @@
  * Subsidiary records (such as triggers or indexes to implement the
  * constraint) are *not* created here.  But we do make dependency links
  * from the constraint to the things it depends on.
+ *
+ * The new constraint's OID is returned.
  */
 Oid
 CreateConstraintEntry(const char *constraintName,
index 32e19c5e4fc02010009fc99a24e168d4f6f65737..002319e8a02f1f79494713f3707adfa70c085741 100644 (file)
@@ -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;
 }
 
 /*
index 573b2deb2d08434f6fe4b78d26193748762a1c54..e6ac3943fcb66e58614e1b825b4597d0a90761eb 100644 (file)
@@ -28,6 +28,7 @@ typedef struct RawColumnDefault
 typedef struct CookedConstraint
 {
        ConstrType      contype;                /* CONSTR_DEFAULT or CONSTR_CHECK */
+       Oid                     conoid;                 /* constr OID if created, otherwise Invalid */
        char       *name;                       /* name, or NULL if none */
        AttrNumber      attnum;                 /* which attr (only for DEFAULT) */
        Node       *expr;                       /* transformed default or check expr */
@@ -101,7 +102,7 @@ extern List *AddRelationNewConstraints(Relation rel,
                                                  bool is_local,
                                                  bool is_internal);
 
-extern void StoreAttrDefault(Relation rel, AttrNumber attnum,
+extern Oid StoreAttrDefault(Relation rel, AttrNumber attnum,
                                 Node *expr, bool is_internal);
 
 extern Node *cookDefault(ParseState *pstate,
index e7cc7a0f7b1d6cb7af0e32673c877aa8de07c44d..a04def96e4cadd6cc569e59d74ee216ee1979ff7 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef INDEX_H
 #define INDEX_H
 
+#include "catalog/objectaddress.h"
 #include "nodes/execnodes.h"
 
 
@@ -63,7 +64,7 @@ extern Oid index_create(Relation heapRelation,
                         bool is_internal,
                         bool if_not_exists);
 
-extern void index_constraint_create(Relation heapRelation,
+extern ObjectAddress index_constraint_create(Relation heapRelation,
                                                Oid indexRelationId,
                                                IndexInfo *indexInfo,
                                                const char *constraintName,