Commit bdc3d7fa authored by Alvaro Herrera's avatar Alvaro Herrera

Return ObjectAddress in many ALTER TABLE sub-routines

Since commit a2e35b53, 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 c504513f started.

Reviewed by Stephen Frost.
parent 06bf0dd6
...@@ -97,7 +97,7 @@ static ObjectAddress AddNewRelationType(const char *typeName, ...@@ -97,7 +97,7 @@ static ObjectAddress AddNewRelationType(const char *typeName,
Oid new_row_type, Oid new_row_type,
Oid new_array_type); Oid new_array_type);
static void RelationRemoveInheritance(Oid relid); 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_validated, bool is_local, int inhcount,
bool is_no_inherit, bool is_internal); bool is_no_inherit, bool is_internal);
static void StoreConstraints(Relation rel, List *cooked_constraints, static void StoreConstraints(Relation rel, List *cooked_constraints,
...@@ -1852,8 +1852,10 @@ heap_drop_with_catalog(Oid relid) ...@@ -1852,8 +1852,10 @@ heap_drop_with_catalog(Oid relid)
/* /*
* Store a default expression for column attnum of relation rel. * 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, StoreAttrDefault(Relation rel, AttrNumber attnum,
Node *expr, bool is_internal) Node *expr, bool is_internal)
{ {
...@@ -1958,6 +1960,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, ...@@ -1958,6 +1960,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
*/ */
InvokeObjectPostCreateHookArg(AttrDefaultRelationId, InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
RelationGetRelid(rel), attnum, is_internal); RelationGetRelid(rel), attnum, is_internal);
return attrdefOid;
} }
/* /*
...@@ -1965,8 +1969,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, ...@@ -1965,8 +1969,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
* *
* Caller is responsible for updating the count of constraints * Caller is responsible for updating the count of constraints
* in the pg_class entry for the relation. * 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, StoreRelCheck(Relation rel, char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount, bool is_validated, bool is_local, int inhcount,
bool is_no_inherit, bool is_internal) bool is_no_inherit, bool is_internal)
...@@ -1976,6 +1982,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr, ...@@ -1976,6 +1982,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
List *varList; List *varList;
int keycount; int keycount;
int16 *attNos; int16 *attNos;
Oid constrOid;
/* /*
* Flatten expression to string form for storage. * Flatten expression to string form for storage.
...@@ -2027,6 +2034,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr, ...@@ -2027,6 +2034,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
/* /*
* Create the Check Constraint * Create the Check Constraint
*/ */
constrOid =
CreateConstraintEntry(ccname, /* Constraint Name */ CreateConstraintEntry(ccname, /* Constraint Name */
RelationGetNamespace(rel), /* namespace */ RelationGetNamespace(rel), /* namespace */
CONSTRAINT_CHECK, /* Constraint Type */ CONSTRAINT_CHECK, /* Constraint Type */
...@@ -2058,11 +2066,15 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr, ...@@ -2058,11 +2066,15 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
pfree(ccbin); pfree(ccbin);
pfree(ccsrc); pfree(ccsrc);
return constrOid;
} }
/* /*
* Store defaults and constraints (passed as a list of CookedConstraint). * 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 * NOTE: only pre-cooked expressions will be passed this way, which is to
* say expressions inherited from an existing relation. Newly parsed * say expressions inherited from an existing relation. Newly parsed
* expressions can be added later, by direct calls to StoreAttrDefault * expressions can be added later, by direct calls to StoreAttrDefault
...@@ -2074,7 +2086,7 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal) ...@@ -2074,7 +2086,7 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
int numchecks = 0; int numchecks = 0;
ListCell *lc; ListCell *lc;
if (!cooked_constraints) if (cooked_constraints == NIL)
return; /* nothing to do */ return; /* nothing to do */
/* /*
...@@ -2091,12 +2103,15 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal) ...@@ -2091,12 +2103,15 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
switch (con->contype) switch (con->contype)
{ {
case CONSTR_DEFAULT: case CONSTR_DEFAULT:
StoreAttrDefault(rel, con->attnum, con->expr, is_internal); con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
is_internal);
break; break;
case CONSTR_CHECK: case CONSTR_CHECK:
StoreRelCheck(rel, con->name, con->expr, !con->skip_validation, con->conoid =
con->is_local, con->inhcount, StoreRelCheck(rel, con->name, con->expr,
con->is_no_inherit, is_internal); !con->skip_validation, con->is_local,
con->inhcount, con->is_no_inherit,
is_internal);
numchecks++; numchecks++;
break; break;
default: default:
...@@ -2184,6 +2199,7 @@ AddRelationNewConstraints(Relation rel, ...@@ -2184,6 +2199,7 @@ AddRelationNewConstraints(Relation rel,
{ {
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell); RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1]; Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
Oid defOid;
expr = cookDefault(pstate, colDef->raw_default, expr = cookDefault(pstate, colDef->raw_default,
atp->atttypid, atp->atttypmod, atp->atttypid, atp->atttypmod,
...@@ -2204,10 +2220,11 @@ AddRelationNewConstraints(Relation rel, ...@@ -2204,10 +2220,11 @@ AddRelationNewConstraints(Relation rel,
(IsA(expr, Const) &&((Const *) expr)->constisnull)) (IsA(expr, Const) &&((Const *) expr)->constisnull))
continue; continue;
StoreAttrDefault(rel, colDef->attnum, expr, is_internal); defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT; cooked->contype = CONSTR_DEFAULT;
cooked->conoid = defOid;
cooked->name = NULL; cooked->name = NULL;
cooked->attnum = colDef->attnum; cooked->attnum = colDef->attnum;
cooked->expr = expr; cooked->expr = expr;
...@@ -2227,6 +2244,7 @@ AddRelationNewConstraints(Relation rel, ...@@ -2227,6 +2244,7 @@ AddRelationNewConstraints(Relation rel,
{ {
Constraint *cdef = (Constraint *) lfirst(cell); Constraint *cdef = (Constraint *) lfirst(cell);
char *ccname; char *ccname;
Oid constrOid;
if (cdef->contype != CONSTR_CHECK) if (cdef->contype != CONSTR_CHECK)
continue; continue;
...@@ -2329,6 +2347,7 @@ AddRelationNewConstraints(Relation rel, ...@@ -2329,6 +2347,7 @@ AddRelationNewConstraints(Relation rel,
/* /*
* OK, store it. * OK, store it.
*/ */
constrOid =
StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local, StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
is_local ? 0 : 1, cdef->is_no_inherit, is_internal); is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
...@@ -2336,6 +2355,7 @@ AddRelationNewConstraints(Relation rel, ...@@ -2336,6 +2355,7 @@ AddRelationNewConstraints(Relation rel,
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_CHECK; cooked->contype = CONSTR_CHECK;
cooked->conoid = constrOid;
cooked->name = ccname; cooked->name = ccname;
cooked->attnum = 0; cooked->attnum = 0;
cooked->expr = expr; cooked->expr = expr;
......
...@@ -1111,7 +1111,8 @@ index_create(Relation heapRelation, ...@@ -1111,7 +1111,8 @@ index_create(Relation heapRelation,
/* /*
* index_constraint_create * 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) * heapRelation: table owning the index (must be suitably locked by caller)
* indexRelationId: OID of the index * indexRelationId: OID of the index
...@@ -1128,7 +1129,7 @@ index_create(Relation heapRelation, ...@@ -1128,7 +1129,7 @@ index_create(Relation heapRelation,
* allow_system_table_mods: allow table to be a system catalog * allow_system_table_mods: allow table to be a system catalog
* is_internal: index is constructed due to internal process * is_internal: index is constructed due to internal process
*/ */
void ObjectAddress
index_constraint_create(Relation heapRelation, index_constraint_create(Relation heapRelation,
Oid indexRelationId, Oid indexRelationId,
IndexInfo *indexInfo, IndexInfo *indexInfo,
...@@ -1316,6 +1317,8 @@ index_constraint_create(Relation heapRelation, ...@@ -1316,6 +1317,8 @@ index_constraint_create(Relation heapRelation,
heap_freetuple(indexTuple); heap_freetuple(indexTuple);
heap_close(pg_index, RowExclusiveLock); heap_close(pg_index, RowExclusiveLock);
} }
return referenced;
} }
/* /*
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
* Subsidiary records (such as triggers or indexes to implement the * Subsidiary records (such as triggers or indexes to implement the
* constraint) are *not* created here. But we do make dependency links * constraint) are *not* created here. But we do make dependency links
* from the constraint to the things it depends on. * from the constraint to the things it depends on.
*
* The new constraint's OID is returned.
*/ */
Oid Oid
CreateConstraintEntry(const char *constraintName, CreateConstraintEntry(const char *constraintName,
......
...@@ -282,9 +282,9 @@ static void AlterIndexNamespaces(Relation classRel, Relation rel, ...@@ -282,9 +282,9 @@ static void AlterIndexNamespaces(Relation classRel, Relation rel,
static void AlterSeqNamespaces(Relation classRel, Relation rel, static void AlterSeqNamespaces(Relation classRel, Relation rel,
Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
LOCKMODE lockmode); LOCKMODE lockmode);
static void ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
bool recurse, bool recursing, LOCKMODE lockmode); 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); bool recurse, bool recursing, LOCKMODE lockmode);
static int transformColumnNameList(Oid relId, List *colList, static int transformColumnNameList(Oid relId, List *colList,
int16 *attnums, Oid *atttypids); int16 *attnums, Oid *atttypids);
...@@ -326,47 +326,47 @@ static List *find_typed_table_dependencies(Oid typeOid, const char *typeName, ...@@ -326,47 +326,47 @@ static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
DropBehavior behavior); DropBehavior behavior);
static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing, static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode); bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, static ObjectAddress ATExecAddColumn(List **wqueue, AlteredTableInfo *tab,
ColumnDef *colDef, bool isOid, Relation rel, ColumnDef *colDef, bool isOid,
bool recurse, bool recursing, LOCKMODE lockmode); bool recurse, bool recursing, LOCKMODE lockmode);
static void check_for_column_name_collision(Relation rel, const char *colname); 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_datatype_dependency(Oid relid, int32 attnum, Oid typid);
static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid); static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse, static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
AlterTableCmd *cmd, LOCKMODE lockmode); AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode); static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
const char *colName, LOCKMODE lockmode); 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); Node *newDefault, LOCKMODE lockmode);
static void ATPrepSetStatistics(Relation rel, const char *colName, static void ATPrepSetStatistics(Relation rel, const char *colName,
Node *newValue, LOCKMODE lockmode); Node *newValue, LOCKMODE lockmode);
static void ATExecSetStatistics(Relation rel, const char *colName, static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName,
Node *newValue, LOCKMODE lockmode); 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); 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); Node *newValue, LOCKMODE lockmode);
static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing, static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
AlterTableCmd *cmd, LOCKMODE lockmode); 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, DropBehavior behavior,
bool recurse, bool recursing, bool recurse, bool recursing,
bool missing_ok, LOCKMODE lockmode); 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); IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
static void ATExecAddConstraint(List **wqueue, static ObjectAddress ATExecAddConstraint(List **wqueue,
AlteredTableInfo *tab, Relation rel, AlteredTableInfo *tab, Relation rel,
Constraint *newConstraint, bool recurse, bool is_readd, Constraint *newConstraint, bool recurse, bool is_readd,
LOCKMODE lockmode); LOCKMODE lockmode);
static void ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, static ObjectAddress ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
IndexStmt *stmt, LOCKMODE lockmode); IndexStmt *stmt, LOCKMODE lockmode);
static void ATAddCheckConstraint(List **wqueue, static ObjectAddress ATAddCheckConstraint(List **wqueue,
AlteredTableInfo *tab, Relation rel, AlteredTableInfo *tab, Relation rel,
Constraint *constr, Constraint *constr,
bool recurse, bool recursing, bool is_readd, bool recurse, bool recursing, bool is_readd,
LOCKMODE lockmode); LOCKMODE lockmode);
static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, static ObjectAddress ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
Constraint *fkconstraint, LOCKMODE lockmode); Constraint *fkconstraint, LOCKMODE lockmode);
static void ATExecDropConstraint(Relation rel, const char *constrName, static void ATExecDropConstraint(Relation rel, const char *constrName,
DropBehavior behavior, DropBehavior behavior,
...@@ -377,9 +377,9 @@ static void ATPrepAlterColumnType(List **wqueue, ...@@ -377,9 +377,9 @@ static void ATPrepAlterColumnType(List **wqueue,
bool recurse, bool recursing, bool recurse, bool recursing,
AlterTableCmd *cmd, LOCKMODE lockmode); AlterTableCmd *cmd, LOCKMODE lockmode);
static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno); 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); AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATExecAlterColumnGenericOptions(Relation rel, const char *colName, static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
List *options, LOCKMODE lockmode); List *options, LOCKMODE lockmode);
static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab,
LOCKMODE lockmode); LOCKMODE lockmode);
...@@ -392,7 +392,7 @@ static void change_owner_fix_column_acls(Oid relationOid, ...@@ -392,7 +392,7 @@ static void change_owner_fix_column_acls(Oid relationOid,
Oid oldOwnerId, Oid newOwnerId); Oid oldOwnerId, Oid newOwnerId);
static void change_owner_recurse_to_sequences(Oid relationOid, static void change_owner_recurse_to_sequences(Oid relationOid,
Oid newOwnerId, LOCKMODE lockmode); Oid newOwnerId, LOCKMODE lockmode);
static void ATExecClusterOn(Relation rel, const char *indexName, static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName,
LOCKMODE lockmode); LOCKMODE lockmode);
static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
static bool ATPrepChangePersistence(Relation rel, bool toLogged); static bool ATPrepChangePersistence(Relation rel, bool toLogged);
...@@ -407,10 +407,10 @@ static void ATExecEnableDisableTrigger(Relation rel, char *trigname, ...@@ -407,10 +407,10 @@ static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
static void ATExecEnableDisableRule(Relation rel, char *rulename, static void ATExecEnableDisableRule(Relation rel, char *rulename,
char fires_when, LOCKMODE lockmode); char fires_when, LOCKMODE lockmode);
static void ATPrepAddInherit(Relation child_rel); static void ATPrepAddInherit(Relation child_rel);
static void ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode); static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
static void ATExecDropInherit(Relation 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 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 ATExecDropOf(Relation rel, LOCKMODE lockmode);
static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode); static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
static void ATExecGenericOptions(Relation rel, List *options); static void ATExecGenericOptions(Relation rel, List *options);
...@@ -623,6 +623,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ...@@ -623,6 +623,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT; cooked->contype = CONSTR_DEFAULT;
cooked->conoid = InvalidOid; /* until created */
cooked->name = NULL; cooked->name = NULL;
cooked->attnum = attnum; cooked->attnum = attnum;
cooked->expr = colDef->cooked_default; cooked->expr = colDef->cooked_default;
...@@ -1742,6 +1743,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, ...@@ -1742,6 +1743,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_CHECK; cooked->contype = CONSTR_CHECK;
cooked->conoid = InvalidOid; /* until created */
cooked->name = pstrdup(name); cooked->name = pstrdup(name);
cooked->attnum = 0; /* not used for constraints */ cooked->attnum = 0; /* not used for constraints */
cooked->expr = expr; cooked->expr = expr;
...@@ -3429,78 +3431,90 @@ static void ...@@ -3429,78 +3431,90 @@ static void
ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
AlterTableCmd *cmd, LOCKMODE lockmode) AlterTableCmd *cmd, LOCKMODE lockmode)
{ {
ObjectAddress address = InvalidObjectAddress;
switch (cmd->subtype) switch (cmd->subtype)
{ {
case AT_AddColumn: /* ADD COLUMN */ case AT_AddColumn: /* ADD COLUMN */
case AT_AddColumnToView: /* add column via CREATE OR REPLACE case AT_AddColumnToView: /* add column via CREATE OR REPLACE
* VIEW */ * VIEW */
ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
false, false, false, lockmode); false, false, false, lockmode);
break; break;
case AT_AddColumnRecurse: case AT_AddColumnRecurse:
ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
false, true, false, lockmode); false, true, false, lockmode);
break; break;
case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */ case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode); address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
break; break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */ case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
ATExecDropNotNull(rel, cmd->name, lockmode); address = ATExecDropNotNull(rel, cmd->name, lockmode);
break; break;
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
ATExecSetNotNull(tab, rel, cmd->name, lockmode); address = ATExecSetNotNull(tab, rel, cmd->name, lockmode);
break; break;
case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */ case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
ATExecSetStatistics(rel, cmd->name, cmd->def, lockmode); address = ATExecSetStatistics(rel, cmd->name, cmd->def, lockmode);
break; break;
case AT_SetOptions: /* ALTER COLUMN SET ( options ) */ 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; break;
case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */ 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; break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
ATExecSetStorage(rel, cmd->name, cmd->def, lockmode); address = ATExecSetStorage(rel, cmd->name, cmd->def, lockmode);
break; break;
case AT_DropColumn: /* DROP COLUMN */ case AT_DropColumn: /* DROP COLUMN */
ATExecDropColumn(wqueue, rel, cmd->name, address = ATExecDropColumn(wqueue, rel, cmd->name,
cmd->behavior, false, false, cmd->missing_ok, lockmode); cmd->behavior, false, false,
cmd->missing_ok, lockmode);
break; break;
case AT_DropColumnRecurse: /* DROP COLUMN with recursion */ case AT_DropColumnRecurse: /* DROP COLUMN with recursion */
ATExecDropColumn(wqueue, rel, cmd->name, address = ATExecDropColumn(wqueue, rel, cmd->name,
cmd->behavior, true, false, cmd->missing_ok, lockmode); cmd->behavior, true, false,
cmd->missing_ok, lockmode);
break; break;
case AT_AddIndex: /* ADD INDEX */ case AT_AddIndex: /* ADD INDEX */
ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false, lockmode); address = ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false,
lockmode);
break; break;
case AT_ReAddIndex: /* ADD INDEX */ case AT_ReAddIndex: /* ADD INDEX */
ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true, lockmode); address = ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true,
lockmode);
break; break;
case AT_AddConstraint: /* ADD CONSTRAINT */ case AT_AddConstraint: /* ADD CONSTRAINT */
address =
ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
false, false, lockmode); false, false, lockmode);
break; break;
case AT_AddConstraintRecurse: /* ADD CONSTRAINT with recursion */ case AT_AddConstraintRecurse: /* ADD CONSTRAINT with recursion */
address =
ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
true, false, lockmode); true, false, lockmode);
break; break;
case AT_ReAddConstraint: /* Re-add pre-existing check case AT_ReAddConstraint: /* Re-add pre-existing check
* constraint */ * constraint */
address =
ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
false, true, lockmode); false, true, lockmode);
break; break;
case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */ case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */
ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def, lockmode); address = ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def,
lockmode);
break; break;
case AT_AlterConstraint: /* ALTER CONSTRAINT */ case AT_AlterConstraint: /* ALTER CONSTRAINT */
ATExecAlterConstraint(rel, cmd, false, false, lockmode); address = ATExecAlterConstraint(rel, cmd, false, false, lockmode);
break; break;
case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */ case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
ATExecValidateConstraint(rel, cmd->name, false, false, lockmode); address = ATExecValidateConstraint(rel, cmd->name, false, false,
lockmode);
break; break;
case AT_ValidateConstraintRecurse: /* VALIDATE CONSTRAINT with case AT_ValidateConstraintRecurse: /* VALIDATE CONSTRAINT with
* recursion */ * recursion */
ATExecValidateConstraint(rel, cmd->name, true, false, lockmode); address = ATExecValidateConstraint(rel, cmd->name, true, false,
lockmode);
break; break;
case AT_DropConstraint: /* DROP CONSTRAINT */ case AT_DropConstraint: /* DROP CONSTRAINT */
ATExecDropConstraint(rel, cmd->name, cmd->behavior, ATExecDropConstraint(rel, cmd->name, cmd->behavior,
...@@ -3513,10 +3527,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -3513,10 +3527,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
cmd->missing_ok, lockmode); cmd->missing_ok, lockmode);
break; break;
case AT_AlterColumnType: /* ALTER COLUMN TYPE */ case AT_AlterColumnType: /* ALTER COLUMN TYPE */
ATExecAlterColumnType(tab, rel, cmd, lockmode); address = ATExecAlterColumnType(tab, rel, cmd, lockmode);
break; break;
case AT_AlterColumnGenericOptions: /* ALTER COLUMN OPTIONS */ case AT_AlterColumnGenericOptions: /* ALTER COLUMN OPTIONS */
ATExecAlterColumnGenericOptions(rel, cmd->name, (List *) cmd->def, lockmode); address =
ATExecAlterColumnGenericOptions(rel, cmd->name,
(List *) cmd->def, lockmode);
break; break;
case AT_ChangeOwner: /* ALTER OWNER */ case AT_ChangeOwner: /* ALTER OWNER */
ATExecChangeOwner(RelationGetRelid(rel), ATExecChangeOwner(RelationGetRelid(rel),
...@@ -3524,7 +3540,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -3524,7 +3540,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
false, lockmode); false, lockmode);
break; break;
case AT_ClusterOn: /* CLUSTER ON */ case AT_ClusterOn: /* CLUSTER ON */
ATExecClusterOn(rel, cmd->name, lockmode); address = ATExecClusterOn(rel, cmd->name, lockmode);
break; break;
case AT_DropCluster: /* SET WITHOUT CLUSTER */ case AT_DropCluster: /* SET WITHOUT CLUSTER */
ATExecDropCluster(rel, lockmode); ATExecDropCluster(rel, lockmode);
...@@ -3535,12 +3551,14 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -3535,12 +3551,14 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
case AT_AddOids: /* SET WITH OIDS */ case AT_AddOids: /* SET WITH OIDS */
/* Use the ADD COLUMN code, unless prep decided to do nothing */ /* Use the ADD COLUMN code, unless prep decided to do nothing */
if (cmd->def != NULL) if (cmd->def != NULL)
address =
ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
true, false, false, lockmode); true, false, false, lockmode);
break; break;
case AT_AddOidsRecurse: /* SET WITH OIDS */ case AT_AddOidsRecurse: /* SET WITH OIDS */
/* Use the ADD COLUMN code, unless prep decided to do nothing */ /* Use the ADD COLUMN code, unless prep decided to do nothing */
if (cmd->def != NULL) if (cmd->def != NULL)
address =
ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def, ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
true, true, false, lockmode); true, true, false, lockmode);
break; break;
...@@ -3613,13 +3631,13 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -3613,13 +3631,13 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
break; break;
case AT_AddInherit: case AT_AddInherit:
ATExecAddInherit(rel, (RangeVar *) cmd->def, lockmode); address = ATExecAddInherit(rel, (RangeVar *) cmd->def, lockmode);
break; break;
case AT_DropInherit: case AT_DropInherit:
ATExecDropInherit(rel, (RangeVar *) cmd->def, lockmode); address = ATExecDropInherit(rel, (RangeVar *) cmd->def, lockmode);
break; break;
case AT_AddOf: case AT_AddOf:
ATExecAddOf(rel, (TypeName *) cmd->def, lockmode); address = ATExecAddOf(rel, (TypeName *) cmd->def, lockmode);
break; break;
case AT_DropOf: case AT_DropOf:
ATExecDropOf(rel, lockmode); ATExecDropOf(rel, lockmode);
...@@ -3642,6 +3660,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -3642,6 +3660,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
break; 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 * Bump the command counter to ensure the next subcommand in the sequence
* can see the changes so far * can see the changes so far
...@@ -4626,7 +4647,11 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing, ...@@ -4626,7 +4647,11 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
cmd->subtype = AT_AddColumnRecurse; 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, ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
ColumnDef *colDef, bool isOid, ColumnDef *colDef, bool isOid,
bool recurse, bool recursing, LOCKMODE lockmode) bool recurse, bool recursing, LOCKMODE lockmode)
...@@ -4647,6 +4672,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -4647,6 +4672,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
List *children; List *children;
ListCell *child; ListCell *child;
AclResult aclresult; AclResult aclresult;
ObjectAddress address;
/* At top level, permission check was done in ATPrepCmd, else do it */ /* At top level, permission check was done in ATPrepCmd, else do it */
if (recursing) if (recursing)
...@@ -4711,7 +4737,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -4711,7 +4737,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
colDef->colname, RelationGetRelationName(rel)))); colDef->colname, RelationGetRelationName(rel))));
heap_close(attrdesc, RowExclusiveLock); heap_close(attrdesc, RowExclusiveLock);
return; return InvalidObjectAddress;
} }
} }
...@@ -4951,12 +4977,15 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -4951,12 +4977,15 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Find or create work queue entry for this table */ /* Find or create work queue entry for this table */
childtab = ATGetQueueEntry(wqueue, childrel); childtab = ATGetQueueEntry(wqueue, childrel);
/* Recurse to child */ /* Recurse to child; return value is ignored */
ATExecAddColumn(wqueue, childtab, childrel, ATExecAddColumn(wqueue, childtab, childrel,
colDef, isOid, recurse, true, lockmode); colDef, isOid, recurse, true, lockmode);
heap_close(childrel, NoLock); 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 ...@@ -5070,8 +5099,11 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC
/* /*
* ALTER TABLE ALTER COLUMN DROP NOT NULL * 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) ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
{ {
HeapTuple tuple; HeapTuple tuple;
...@@ -5079,6 +5111,7 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) ...@@ -5079,6 +5111,7 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
Relation attr_rel; Relation attr_rel;
List *indexoidlist; List *indexoidlist;
ListCell *indexoidscan; ListCell *indexoidscan;
ObjectAddress address;
/* /*
* lookup the attribute * lookup the attribute
...@@ -5156,24 +5189,35 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) ...@@ -5156,24 +5189,35 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
/* keep the system catalog indexes current */ /* keep the system catalog indexes current */
CatalogUpdateIndexes(attr_rel, tuple); CatalogUpdateIndexes(attr_rel, tuple);
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
} }
else
address = InvalidObjectAddress;
InvokeObjectPostAlterHook(RelationRelationId, InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel), attnum); RelationGetRelid(rel), attnum);
heap_close(attr_rel, RowExclusiveLock); heap_close(attr_rel, RowExclusiveLock);
return address;
} }
/* /*
* ALTER TABLE ALTER COLUMN SET NOT NULL * 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, ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
const char *colName, LOCKMODE lockmode) const char *colName, LOCKMODE lockmode)
{ {
HeapTuple tuple; HeapTuple tuple;
AttrNumber attnum; AttrNumber attnum;
Relation attr_rel; Relation attr_rel;
ObjectAddress address;
/* /*
* lookup the attribute * lookup the attribute
...@@ -5211,22 +5255,32 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, ...@@ -5211,22 +5255,32 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
/* Tell Phase 3 it needs to test the constraint */ /* Tell Phase 3 it needs to test the constraint */
tab->new_notnull = true; tab->new_notnull = true;
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
} }
else
address = InvalidObjectAddress;
InvokeObjectPostAlterHook(RelationRelationId, InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel), attnum); RelationGetRelid(rel), attnum);
heap_close(attr_rel, RowExclusiveLock); heap_close(attr_rel, RowExclusiveLock);
return address;
} }
/* /*
* ALTER TABLE ALTER COLUMN SET/DROP DEFAULT * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT
*
* Return the address of the affected column.
*/ */
static void static ObjectAddress
ATExecColumnDefault(Relation rel, const char *colName, ATExecColumnDefault(Relation rel, const char *colName,
Node *newDefault, LOCKMODE lockmode) Node *newDefault, LOCKMODE lockmode)
{ {
AttrNumber attnum; AttrNumber attnum;
ObjectAddress address;
/* /*
* get the number of the attribute * get the number of the attribute
...@@ -5273,6 +5327,10 @@ ATExecColumnDefault(Relation rel, const char *colName, ...@@ -5273,6 +5327,10 @@ ATExecColumnDefault(Relation rel, const char *colName,
AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
false, true, false); false, true, false);
} }
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
return address;
} }
/* /*
...@@ -5302,13 +5360,18 @@ ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE ...@@ -5302,13 +5360,18 @@ ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE
RelationGetRelationName(rel)); 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) ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
{ {
int newtarget; int newtarget;
Relation attrelation; Relation attrelation;
HeapTuple tuple; HeapTuple tuple;
Form_pg_attribute attrtuple; Form_pg_attribute attrtuple;
AttrNumber attnum;
ObjectAddress address;
Assert(IsA(newValue, Integer)); Assert(IsA(newValue, Integer));
newtarget = intVal(newValue); newtarget = intVal(newValue);
...@@ -5343,7 +5406,8 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE ...@@ -5343,7 +5406,8 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE
colName, RelationGetRelationName(rel)))); colName, RelationGetRelationName(rel))));
attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
if (attrtuple->attnum <= 0) attnum = attrtuple->attnum;
if (attnum <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot alter system column \"%s\"", errmsg("cannot alter system column \"%s\"",
...@@ -5359,12 +5423,19 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE ...@@ -5359,12 +5423,19 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE
InvokeObjectPostAlterHook(RelationRelationId, InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel), RelationGetRelid(rel),
attrtuple->attnum); attrtuple->attnum);
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
heap_freetuple(tuple); heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock); 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, ATExecSetOptions(Relation rel, const char *colName, Node *options,
bool isReset, LOCKMODE lockmode) bool isReset, LOCKMODE lockmode)
{ {
...@@ -5372,9 +5443,11 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, ...@@ -5372,9 +5443,11 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
HeapTuple tuple, HeapTuple tuple,
newtuple; newtuple;
Form_pg_attribute attrtuple; Form_pg_attribute attrtuple;
AttrNumber attnum;
Datum datum, Datum datum,
newOptions; newOptions;
bool isnull; bool isnull;
ObjectAddress address;
Datum repl_val[Natts_pg_attribute]; Datum repl_val[Natts_pg_attribute];
bool repl_null[Natts_pg_attribute]; bool repl_null[Natts_pg_attribute];
bool repl_repl[Natts_pg_attribute]; bool repl_repl[Natts_pg_attribute];
...@@ -5390,7 +5463,8 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, ...@@ -5390,7 +5463,8 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
colName, RelationGetRelationName(rel)))); colName, RelationGetRelationName(rel))));
attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
if (attrtuple->attnum <= 0) attnum = attrtuple->attnum;
if (attnum <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot alter system column \"%s\"", errmsg("cannot alter system column \"%s\"",
...@@ -5424,17 +5498,24 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, ...@@ -5424,17 +5498,24 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
InvokeObjectPostAlterHook(RelationRelationId, InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel), RelationGetRelid(rel),
attrtuple->attnum); attrtuple->attnum);
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
heap_freetuple(newtuple); heap_freetuple(newtuple);
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
heap_close(attrelation, RowExclusiveLock); heap_close(attrelation, RowExclusiveLock);
return address;
} }
/* /*
* ALTER TABLE ALTER COLUMN SET STORAGE * 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) ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
{ {
char *storagemode; char *storagemode;
...@@ -5442,6 +5523,8 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc ...@@ -5442,6 +5523,8 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
Relation attrelation; Relation attrelation;
HeapTuple tuple; HeapTuple tuple;
Form_pg_attribute attrtuple; Form_pg_attribute attrtuple;
AttrNumber attnum;
ObjectAddress address;
Assert(IsA(newValue, String)); Assert(IsA(newValue, String));
storagemode = strVal(newValue); storagemode = strVal(newValue);
...@@ -5474,7 +5557,8 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc ...@@ -5474,7 +5557,8 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
colName, RelationGetRelationName(rel)))); colName, RelationGetRelationName(rel))));
attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
if (attrtuple->attnum <= 0) attnum = attrtuple->attnum;
if (attnum <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot alter system column \"%s\"", errmsg("cannot alter system column \"%s\"",
...@@ -5504,6 +5588,10 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc ...@@ -5504,6 +5588,10 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
heap_freetuple(tuple); heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock); 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, ...@@ -5532,7 +5620,10 @@ ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
cmd->subtype = AT_DropColumnRecurse; cmd->subtype = AT_DropColumnRecurse;
} }
static void /*
* Return value is that of the dropped column.
*/
static ObjectAddress
ATExecDropColumn(List **wqueue, Relation rel, const char *colName, ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
DropBehavior behavior, DropBehavior behavior,
bool recurse, bool recursing, bool recurse, bool recursing,
...@@ -5566,7 +5657,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, ...@@ -5566,7 +5657,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
ereport(NOTICE, ereport(NOTICE,
(errmsg("column \"%s\" of relation \"%s\" does not exist, skipping", (errmsg("column \"%s\" of relation \"%s\" does not exist, skipping",
colName, RelationGetRelationName(rel)))); colName, RelationGetRelationName(rel))));
return; return InvalidObjectAddress;
} }
} }
targetatt = (Form_pg_attribute) GETSTRUCT(tuple); targetatt = (Form_pg_attribute) GETSTRUCT(tuple);
...@@ -5720,6 +5811,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, ...@@ -5720,6 +5811,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
/* Tell Phase 3 to physically remove the OID column */ /* Tell Phase 3 to physically remove the OID column */
tab->rewrite |= AT_REWRITE_ALTER_OID; tab->rewrite |= AT_REWRITE_ALTER_OID;
} }
return object;
} }
/* /*
...@@ -5728,8 +5821,10 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, ...@@ -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 * There is no such command in the grammar, but parse_utilcmd.c converts
* UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands. This lets * UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands. This lets
* us schedule creation of the index at the appropriate time during ALTER. * 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, ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode) IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode)
{ {
...@@ -5772,12 +5867,16 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel, ...@@ -5772,12 +5867,16 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
RelationPreserveStorage(irel->rd_node, true); RelationPreserveStorage(irel->rd_node, true);
index_close(irel, NoLock); index_close(irel, NoLock);
} }
return address;
} }
/* /*
* ALTER TABLE ADD CONSTRAINT USING INDEX * ALTER TABLE ADD CONSTRAINT USING INDEX
*
* Returns the address of the new constraint.
*/ */
static void static ObjectAddress
ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
IndexStmt *stmt, LOCKMODE lockmode) IndexStmt *stmt, LOCKMODE lockmode)
{ {
...@@ -5787,6 +5886,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -5787,6 +5886,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
IndexInfo *indexInfo; IndexInfo *indexInfo;
char *constraintName; char *constraintName;
char constraintType; char constraintType;
ObjectAddress address;
Assert(IsA(stmt, IndexStmt)); Assert(IsA(stmt, IndexStmt));
Assert(OidIsValid(index_oid)); Assert(OidIsValid(index_oid));
...@@ -5831,7 +5931,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -5831,7 +5931,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
constraintType = CONSTRAINT_UNIQUE; constraintType = CONSTRAINT_UNIQUE;
/* Create the catalog entries for the constraint */ /* Create the catalog entries for the constraint */
index_constraint_create(rel, address = index_constraint_create(rel,
index_oid, index_oid,
indexInfo, indexInfo,
constraintName, constraintName,
...@@ -5845,16 +5945,23 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -5845,16 +5945,23 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
false); /* is_internal */ false); /* is_internal */
index_close(indexRel, NoLock); index_close(indexRel, NoLock);
return address;
} }
/* /*
* ALTER TABLE ADD CONSTRAINT * 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, ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
Constraint *newConstraint, bool recurse, bool is_readd, Constraint *newConstraint, bool recurse, bool is_readd,
LOCKMODE lockmode) LOCKMODE lockmode)
{ {
ObjectAddress address = InvalidObjectAddress;
Assert(IsA(newConstraint, Constraint)); Assert(IsA(newConstraint, Constraint));
/* /*
...@@ -5865,6 +5972,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5865,6 +5972,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
switch (newConstraint->contype) switch (newConstraint->contype)
{ {
case CONSTR_CHECK: case CONSTR_CHECK:
address =
ATAddCheckConstraint(wqueue, tab, rel, ATAddCheckConstraint(wqueue, tab, rel,
newConstraint, recurse, false, is_readd, newConstraint, recurse, false, is_readd,
lockmode); lockmode);
...@@ -5898,17 +6006,22 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5898,17 +6006,22 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
RelationGetNamespace(rel), RelationGetNamespace(rel),
NIL); NIL);
ATAddForeignKeyConstraint(tab, rel, newConstraint, lockmode); address = ATAddForeignKeyConstraint(tab, rel, newConstraint,
lockmode);
break; break;
default: default:
elog(ERROR, "unrecognized constraint type: %d", elog(ERROR, "unrecognized constraint type: %d",
(int) newConstraint->contype); (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. * Subroutine for ATExecAddConstraint.
* *
...@@ -5927,7 +6040,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5927,7 +6040,7 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
* "is_readd" flag for that; just setting recurse=false would result in an * "is_readd" flag for that; just setting recurse=false would result in an
* error if there are child tables. * error if there are child tables.
*/ */
static void static ObjectAddress
ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
Constraint *constr, bool recurse, bool recursing, Constraint *constr, bool recurse, bool recursing,
bool is_readd, LOCKMODE lockmode) bool is_readd, LOCKMODE lockmode)
...@@ -5936,6 +6049,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5936,6 +6049,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
ListCell *lcon; ListCell *lcon;
List *children; List *children;
ListCell *child; ListCell *child;
ObjectAddress address = InvalidObjectAddress;
/* At top level, permission check was done in ATPrepCmd, else do it */ /* At top level, permission check was done in ATPrepCmd, else do it */
if (recursing) if (recursing)
...@@ -5957,6 +6071,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5957,6 +6071,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
!recursing, /* is_local */ !recursing, /* is_local */
is_readd); /* is_internal */ 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 */ /* Add each to-be-validated constraint to Phase 3's queue */
foreach(lcon, newcons) foreach(lcon, newcons)
{ {
...@@ -5978,6 +6095,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5978,6 +6095,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Save the actually assigned name if it was defaulted */ /* Save the actually assigned name if it was defaulted */
if (constr->conname == NULL) if (constr->conname == NULL)
constr->conname = ccon->name; constr->conname = ccon->name;
ObjectAddressSet(address, ConstraintRelationId, ccon->conoid);
} }
/* At this point we must have a locked-down name to use */ /* At this point we must have a locked-down name to use */
...@@ -5993,7 +6112,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -5993,7 +6112,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
* incorrect value for coninhcount. * incorrect value for coninhcount.
*/ */
if (newcons == NIL) if (newcons == NIL)
return; return address;
/* /*
* If adding a NO INHERIT constraint, no need to find our children. * If adding a NO INHERIT constraint, no need to find our children.
...@@ -6001,7 +6120,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -6001,7 +6120,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
* handled at higher levels). * handled at higher levels).
*/ */
if (constr->is_no_inherit || is_readd) if (constr->is_no_inherit || is_readd)
return; return address;
/* /*
* Propagate to children as appropriate. Unlike most other ALTER * Propagate to children as appropriate. Unlike most other ALTER
...@@ -6039,16 +6158,19 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -6039,16 +6158,19 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
heap_close(childrel, NoLock); 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 * Subroutine for ATExecAddConstraint. Must already hold exclusive
* lock on the rel, and have done appropriate validity checks for it. * lock on the rel, and have done appropriate validity checks for it.
* We do permissions checks here, however. * We do permissions checks here, however.
*/ */
static void static ObjectAddress
ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
Constraint *fkconstraint, LOCKMODE lockmode) Constraint *fkconstraint, LOCKMODE lockmode)
{ {
...@@ -6067,6 +6189,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -6067,6 +6189,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
Oid indexOid; Oid indexOid;
Oid constrOid; Oid constrOid;
bool old_check_ok; bool old_check_ok;
ObjectAddress address;
ListCell *old_pfeqop_item = list_head(fkconstraint->old_conpfeqop); ListCell *old_pfeqop_item = list_head(fkconstraint->old_conpfeqop);
/* /*
...@@ -6414,6 +6537,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -6414,6 +6537,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
0, /* inhcount */ 0, /* inhcount */
true, /* isnoinherit */ true, /* isnoinherit */
false); /* is_internal */ false); /* is_internal */
ObjectAddressSet(address, ConstraintRelationId, constrOid);
/* /*
* Create the triggers that will enforce the constraint. * Create the triggers that will enforce the constraint.
...@@ -6447,6 +6571,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -6447,6 +6571,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
* Close pk table, but keep lock until we've committed. * Close pk table, but keep lock until we've committed.
*/ */
heap_close(pkrel, NoLock); heap_close(pkrel, NoLock);
return address;
} }
/* /*
...@@ -6458,8 +6584,11 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, ...@@ -6458,8 +6584,11 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
* Foreign keys do not inherit, so we purposely ignore the * Foreign keys do not inherit, so we purposely ignore the
* recursion bit here, but we keep the API the same for when * recursion bit here, but we keep the API the same for when
* other constraint types are supported. * 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, ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
bool recurse, bool recursing, LOCKMODE lockmode) bool recurse, bool recursing, LOCKMODE lockmode)
{ {
...@@ -6470,6 +6599,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, ...@@ -6470,6 +6599,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
Form_pg_constraint currcon = NULL; Form_pg_constraint currcon = NULL;
Constraint *cmdcon = NULL; Constraint *cmdcon = NULL;
bool found = false; bool found = false;
ObjectAddress address;
Assert(IsA(cmd->def, Constraint)); Assert(IsA(cmd->def, Constraint));
cmdcon = (Constraint *) cmd->def; cmdcon = (Constraint *) cmd->def;
...@@ -6571,11 +6701,18 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, ...@@ -6571,11 +6701,18 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
* Invalidate relcache so that others see the new attributes. * Invalidate relcache so that others see the new attributes.
*/ */
CacheInvalidateRelcache(rel); CacheInvalidateRelcache(rel);
ObjectAddressSet(address, ConstraintRelationId,
HeapTupleGetOid(contuple));
} }
else
address = InvalidObjectAddress;
systable_endscan(scan); systable_endscan(scan);
heap_close(conrel, RowExclusiveLock); heap_close(conrel, RowExclusiveLock);
return address;
} }
/* /*
...@@ -6585,8 +6722,11 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, ...@@ -6585,8 +6722,11 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
* there's no good way to skip recursing when handling foreign keys: there is * 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 * no need to lock children in that case, yet we wouldn't be able to avoid
* doing so at that level. * 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, ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
bool recursing, LOCKMODE lockmode) bool recursing, LOCKMODE lockmode)
{ {
...@@ -6596,6 +6736,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, ...@@ -6596,6 +6736,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
HeapTuple tuple; HeapTuple tuple;
Form_pg_constraint con = NULL; Form_pg_constraint con = NULL;
bool found = false; bool found = false;
ObjectAddress address;
conrel = heap_open(ConstraintRelationId, RowExclusiveLock); conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
...@@ -6639,7 +6780,6 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, ...@@ -6639,7 +6780,6 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
if (con->contype == CONSTRAINT_FOREIGN) if (con->contype == CONSTRAINT_FOREIGN)
{ {
Oid conid = HeapTupleGetOid(tuple);
Relation refrel; Relation refrel;
/* /*
...@@ -6654,7 +6794,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, ...@@ -6654,7 +6794,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
validateForeignKeyConstraint(constrName, rel, refrel, validateForeignKeyConstraint(constrName, rel, refrel,
con->conindid, con->conindid,
conid); HeapTupleGetOid(tuple));
heap_close(refrel, NoLock); heap_close(refrel, NoLock);
/* /*
...@@ -6730,11 +6870,18 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, ...@@ -6730,11 +6870,18 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
HeapTupleGetOid(tuple), 0); HeapTupleGetOid(tuple), 0);
heap_freetuple(copyTuple); heap_freetuple(copyTuple);
ObjectAddressSet(address, ConstraintRelationId,
HeapTupleGetOid(tuple));
} }
else
address = InvalidObjectAddress; /* already validated */
systable_endscan(scan); systable_endscan(scan);
heap_close(conrel, RowExclusiveLock); heap_close(conrel, RowExclusiveLock);
return address;
} }
...@@ -7825,7 +7972,12 @@ ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno) ...@@ -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, ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
AlterTableCmd *cmd, LOCKMODE lockmode) AlterTableCmd *cmd, LOCKMODE lockmode)
{ {
...@@ -7846,6 +7998,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, ...@@ -7846,6 +7998,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
ScanKeyData key[3]; ScanKeyData key[3];
SysScanDesc scan; SysScanDesc scan;
HeapTuple depTup; HeapTuple depTup;
ObjectAddress address;
attrelation = heap_open(AttributeRelationId, RowExclusiveLock); attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
...@@ -8217,11 +8370,19 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, ...@@ -8217,11 +8370,19 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
StoreAttrDefault(rel, attnum, defaultexpr, true); StoreAttrDefault(rel, attnum, defaultexpr, true);
} }
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
/* Cleanup */ /* Cleanup */
heap_freetuple(heapTup); heap_freetuple(heapTup);
return address;
} }
static void /*
* Returns the address of the modified column
*/
static ObjectAddress
ATExecAlterColumnGenericOptions(Relation rel, ATExecAlterColumnGenericOptions(Relation rel,
const char *colName, const char *colName,
List *options, List *options,
...@@ -8240,9 +8401,11 @@ ATExecAlterColumnGenericOptions(Relation rel, ...@@ -8240,9 +8401,11 @@ ATExecAlterColumnGenericOptions(Relation rel,
Datum datum; Datum datum;
Form_pg_foreign_table fttableform; Form_pg_foreign_table fttableform;
Form_pg_attribute atttableform; Form_pg_attribute atttableform;
AttrNumber attnum;
ObjectAddress address;
if (options == NIL) if (options == NIL)
return; return InvalidObjectAddress;
/* First, determine FDW validator associated to the foreign table. */ /* First, determine FDW validator associated to the foreign table. */
ftrel = heap_open(ForeignTableRelationId, AccessShareLock); ftrel = heap_open(ForeignTableRelationId, AccessShareLock);
...@@ -8269,7 +8432,8 @@ ATExecAlterColumnGenericOptions(Relation rel, ...@@ -8269,7 +8432,8 @@ ATExecAlterColumnGenericOptions(Relation rel,
/* Prevent them from altering a system attribute */ /* Prevent them from altering a system attribute */
atttableform = (Form_pg_attribute) GETSTRUCT(tuple); atttableform = (Form_pg_attribute) GETSTRUCT(tuple);
if (atttableform->attnum <= 0) attnum = atttableform->attnum;
if (attnum <= 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot alter system column \"%s\"", colName))); errmsg("cannot alter system column \"%s\"", colName)));
...@@ -8312,12 +8476,16 @@ ATExecAlterColumnGenericOptions(Relation rel, ...@@ -8312,12 +8476,16 @@ ATExecAlterColumnGenericOptions(Relation rel,
InvokeObjectPostAlterHook(RelationRelationId, InvokeObjectPostAlterHook(RelationRelationId,
RelationGetRelid(rel), RelationGetRelid(rel),
atttableform->attnum); atttableform->attnum);
ObjectAddressSubSet(address, RelationRelationId,
RelationGetRelid(rel), attnum);
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
heap_close(attrel, RowExclusiveLock); heap_close(attrel, RowExclusiveLock);
heap_freetuple(newtuple); heap_freetuple(newtuple);
return address;
} }
/* /*
...@@ -8958,11 +9126,14 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lock ...@@ -8958,11 +9126,14 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lock
* ALTER TABLE CLUSTER ON * ALTER TABLE CLUSTER ON
* *
* The only thing we have to do is to change the indisclustered bits. * 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) ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
{ {
Oid indexOid; Oid indexOid;
ObjectAddress address;
indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace); indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
...@@ -8977,6 +9148,11 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode) ...@@ -8977,6 +9148,11 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
/* And do the work */ /* And do the work */
mark_index_clustered(rel, indexOid, false); mark_index_clustered(rel, indexOid, false);
ObjectAddressSet(address,
RelationRelationId, indexOid);
return address;
} }
/* /*
...@@ -9677,7 +9853,10 @@ ATPrepAddInherit(Relation child_rel) ...@@ -9677,7 +9853,10 @@ ATPrepAddInherit(Relation child_rel)
errmsg("cannot change inheritance of typed table"))); 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) ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
{ {
Relation parent_rel, Relation parent_rel,
...@@ -9687,6 +9866,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) ...@@ -9687,6 +9866,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
HeapTuple inheritsTuple; HeapTuple inheritsTuple;
int32 inhseqno; int32 inhseqno;
List *children; List *children;
ObjectAddress address;
/* /*
* A self-exclusive lock is needed here. See the similar case in * A self-exclusive lock is needed here. See the similar case in
...@@ -9801,11 +9981,16 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) ...@@ -9801,11 +9981,16 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
inhseqno + 1, inhseqno + 1,
catalogRelation); catalogRelation);
ObjectAddressSet(address, RelationRelationId,
RelationGetRelid(parent_rel));
/* Now we're done with pg_inherits */ /* Now we're done with pg_inherits */
heap_close(catalogRelation, RowExclusiveLock); heap_close(catalogRelation, RowExclusiveLock);
/* keep our lock on the parent relation until commit */ /* keep our lock on the parent relation until commit */
heap_close(parent_rel, NoLock); heap_close(parent_rel, NoLock);
return address;
} }
/* /*
...@@ -10073,11 +10258,14 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) ...@@ -10073,11 +10258,14 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
* *
* coninhcount and conislocal for inherited constraints are adjusted in * coninhcount and conislocal for inherited constraints are adjusted in
* exactly the same way. * 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) ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
{ {
Relation parent_rel; Relation parent_rel;
Oid parent_oid;
Relation catalogRelation; Relation catalogRelation;
SysScanDesc scan; SysScanDesc scan;
ScanKeyData key[3]; ScanKeyData key[3];
...@@ -10086,6 +10274,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) ...@@ -10086,6 +10274,7 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
constraintTuple; constraintTuple;
List *connames; List *connames;
bool found = false; bool found = false;
ObjectAddress address;
/* /*
* AccessShareLock on the parent is probably enough, seeing that DROP * AccessShareLock on the parent is probably enough, seeing that DROP
...@@ -10246,6 +10435,8 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) ...@@ -10246,6 +10435,8 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
} }
} }
parent_oid = RelationGetRelid(parent_rel);
systable_endscan(scan); systable_endscan(scan);
heap_close(catalogRelation, RowExclusiveLock); heap_close(catalogRelation, RowExclusiveLock);
...@@ -10264,6 +10455,10 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode) ...@@ -10264,6 +10455,10 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
/* keep our lock on the parent relation until commit */ /* keep our lock on the parent relation until commit */
heap_close(parent_rel, NoLock); 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) ...@@ -10321,8 +10516,10 @@ drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
* TABLE OF. All attname, atttypid, atttypmod and attcollation must match. The * TABLE OF. All attname, atttypid, atttypmod and attcollation must match. The
* subject table must not have inheritance parents. These restrictions ensure * subject table must not have inheritance parents. These restrictions ensure
* that you cannot create a configuration impossible with CREATE TABLE OF alone. * 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) ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
{ {
Oid relid = RelationGetRelid(rel); Oid relid = RelationGetRelid(rel);
...@@ -10451,6 +10648,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) ...@@ -10451,6 +10648,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
heap_close(relationRelation, RowExclusiveLock); heap_close(relationRelation, RowExclusiveLock);
ReleaseSysCache(typetuple); ReleaseSysCache(typetuple);
return typeobj;
} }
/* /*
......
...@@ -28,6 +28,7 @@ typedef struct RawColumnDefault ...@@ -28,6 +28,7 @@ typedef struct RawColumnDefault
typedef struct CookedConstraint typedef struct CookedConstraint
{ {
ConstrType contype; /* CONSTR_DEFAULT or CONSTR_CHECK */ ConstrType contype; /* CONSTR_DEFAULT or CONSTR_CHECK */
Oid conoid; /* constr OID if created, otherwise Invalid */
char *name; /* name, or NULL if none */ char *name; /* name, or NULL if none */
AttrNumber attnum; /* which attr (only for DEFAULT) */ AttrNumber attnum; /* which attr (only for DEFAULT) */
Node *expr; /* transformed default or check expr */ Node *expr; /* transformed default or check expr */
...@@ -101,7 +102,7 @@ extern List *AddRelationNewConstraints(Relation rel, ...@@ -101,7 +102,7 @@ extern List *AddRelationNewConstraints(Relation rel,
bool is_local, bool is_local,
bool is_internal); bool is_internal);
extern void StoreAttrDefault(Relation rel, AttrNumber attnum, extern Oid StoreAttrDefault(Relation rel, AttrNumber attnum,
Node *expr, bool is_internal); Node *expr, bool is_internal);
extern Node *cookDefault(ParseState *pstate, extern Node *cookDefault(ParseState *pstate,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#ifndef INDEX_H #ifndef INDEX_H
#define INDEX_H #define INDEX_H
#include "catalog/objectaddress.h"
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
...@@ -63,7 +64,7 @@ extern Oid index_create(Relation heapRelation, ...@@ -63,7 +64,7 @@ extern Oid index_create(Relation heapRelation,
bool is_internal, bool is_internal,
bool if_not_exists); bool if_not_exists);
extern void index_constraint_create(Relation heapRelation, extern ObjectAddress index_constraint_create(Relation heapRelation,
Oid indexRelationId, Oid indexRelationId,
IndexInfo *indexInfo, IndexInfo *indexInfo,
const char *constraintName, const char *constraintName,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment