Return ObjectAddress in many ALTER TABLE sub-routines

Since commit a2e35b53c3, 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 c504513f83 started.

Reviewed by Stephen Frost.
This commit is contained in:
Alvaro Herrera 2015-03-25 17:17:56 -03:00
parent 06bf0dd6e3
commit bdc3d7fa23
6 changed files with 380 additions and 154 deletions

View 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;

View 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;
}
/*

View 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,

File diff suppressed because it is too large Load Diff

View 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,

View 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,