@@ -394,14 +394,21 @@ static ObjectAddress ATExecAlterConstraint(List **wqueue, Relation rel,
394
394
bool recurse, LOCKMODE lockmode);
395
395
static bool ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon, Relation conrel,
396
396
Relation tgrel, Relation rel, HeapTuple contuple,
397
- bool recurse, List **otherrelids, LOCKMODE lockmode);
397
+ bool recurse, LOCKMODE lockmode);
398
+ static bool ATExecAlterConstrDeferrability(List **wqueue, ATAlterConstraint *cmdcon,
399
+ Relation conrel, Relation tgrel, Relation rel,
400
+ HeapTuple contuple, bool recurse,
401
+ List **otherrelids, LOCKMODE lockmode);
402
+ static bool ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon,
403
+ Relation conrel, Relation rel,
404
+ HeapTuple contuple, LOCKMODE lockmode);
398
405
static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
399
406
bool deferrable, bool initdeferred,
400
407
List **otherrelids);
401
- static void ATExecAlterChildConstr (List **wqueue, ATAlterConstraint *cmdcon,
402
- Relation conrel, Relation tgrel, Relation rel,
403
- HeapTuple contuple, bool recurse, List **otherrelids ,
404
- LOCKMODE lockmode);
408
+ static void AlterConstrDeferrabilityRecurse (List **wqueue, ATAlterConstraint *cmdcon,
409
+ Relation conrel, Relation tgrel, Relation rel,
410
+ HeapTuple contuple, bool recurse,
411
+ List **otherrelids, LOCKMODE lockmode);
405
412
static void AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel,
406
413
HeapTuple contuple);
407
414
static ObjectAddress ATExecValidateConstraint(List **wqueue,
@@ -11925,7 +11932,6 @@ ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon,
11925
11932
HeapTuple contuple;
11926
11933
Form_pg_constraint currcon;
11927
11934
ObjectAddress address;
11928
- List *otherrelids = NIL;
11929
11935
11930
11936
/*
11931
11937
* Disallow altering ONLY a partitioned table, as it would make no sense.
@@ -12038,17 +12044,9 @@ ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon,
12038
12044
* Do the actual catalog work, and recurse if necessary.
12039
12045
*/
12040
12046
if (ATExecAlterConstraintInternal(wqueue, cmdcon, conrel, tgrel, rel,
12041
- contuple, recurse, &otherrelids, lockmode))
12047
+ contuple, recurse, lockmode))
12042
12048
ObjectAddressSet(address, ConstraintRelationId, currcon->oid);
12043
12049
12044
- /*
12045
- * ATExecAlterConstraintInternal already invalidated relcache for the
12046
- * relations having the constraint itself; here we also invalidate for
12047
- * relations that have any triggers that are part of the constraint.
12048
- */
12049
- foreach_oid(relid, otherrelids)
12050
- CacheInvalidateRelcacheByRelid(relid);
12051
-
12052
12050
systable_endscan(scan);
12053
12051
12054
12052
table_close(tgrel, RowExclusiveLock);
@@ -12058,8 +12056,51 @@ ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon,
12058
12056
}
12059
12057
12060
12058
/*
12061
- * Recursive subroutine of ATExecAlterConstraint. Returns true if the
12062
- * constraint is altered.
12059
+ * A subroutine of ATExecAlterConstraint that calls the respective routines for
12060
+ * altering constraint attributes.
12061
+ */
12062
+ static bool
12063
+ ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon,
12064
+ Relation conrel, Relation tgrel, Relation rel,
12065
+ HeapTuple contuple, bool recurse,
12066
+ LOCKMODE lockmode)
12067
+ {
12068
+ bool changed = false;
12069
+ List *otherrelids = NIL;
12070
+
12071
+ /*
12072
+ * Do the catalog work for the deferrability change, recurse if necessary.
12073
+ */
12074
+ if (cmdcon->alterDeferrability &&
12075
+ ATExecAlterConstrDeferrability(wqueue, cmdcon, conrel, tgrel, rel,
12076
+ contuple, recurse, &otherrelids,
12077
+ lockmode))
12078
+ {
12079
+ /*
12080
+ * AlterConstrUpdateConstraintEntry already invalidated relcache for
12081
+ * the relations having the constraint itself; here we also invalidate
12082
+ * for relations that have any triggers that are part of the
12083
+ * constraint.
12084
+ */
12085
+ foreach_oid(relid, otherrelids)
12086
+ CacheInvalidateRelcacheByRelid(relid);
12087
+
12088
+ changed = true;
12089
+ }
12090
+
12091
+ /*
12092
+ * Do the catalog work for the inheritability change.
12093
+ */
12094
+ if (cmdcon->alterInheritability &&
12095
+ ATExecAlterConstrInheritability(wqueue, cmdcon, conrel, rel, contuple,
12096
+ lockmode))
12097
+ changed = true;
12098
+
12099
+ return changed;
12100
+ }
12101
+
12102
+ /*
12103
+ * Returns true if the constraint's deferrability is altered.
12063
12104
*
12064
12105
* *otherrelids is appended OIDs of relations containing affected triggers.
12065
12106
*
@@ -12069,31 +12110,32 @@ ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon,
12069
12110
* but existing releases don't do that.)
12070
12111
*/
12071
12112
static bool
12072
- ATExecAlterConstraintInternal (List **wqueue, ATAlterConstraint *cmdcon,
12073
- Relation conrel, Relation tgrel, Relation rel,
12074
- HeapTuple contuple, bool recurse,
12075
- List **otherrelids, LOCKMODE lockmode)
12113
+ ATExecAlterConstrDeferrability (List **wqueue, ATAlterConstraint *cmdcon,
12114
+ Relation conrel, Relation tgrel, Relation rel,
12115
+ HeapTuple contuple, bool recurse,
12116
+ List **otherrelids, LOCKMODE lockmode)
12076
12117
{
12077
12118
Form_pg_constraint currcon;
12078
- Oid refrelid = InvalidOid ;
12119
+ Oid refrelid;
12079
12120
bool changed = false;
12080
12121
12081
12122
/* since this function recurses, it could be driven to stack overflow */
12082
12123
check_stack_depth();
12083
12124
12125
+ Assert(cmdcon->alterDeferrability);
12126
+
12084
12127
currcon = (Form_pg_constraint) GETSTRUCT(contuple);
12085
- if (currcon->contype == CONSTRAINT_FOREIGN)
12086
- refrelid = currcon->confrelid;
12128
+ refrelid = currcon->confrelid;
12129
+
12130
+ /* Should be foreign key constraint */
12131
+ Assert(currcon->contype == CONSTRAINT_FOREIGN);
12087
12132
12088
12133
/*
12089
- * Update pg_constraint with the flags from cmdcon.
12090
- *
12091
12134
* If called to modify a constraint that's already in the desired state,
12092
12135
* silently do nothing.
12093
12136
*/
12094
- if (cmdcon->alterDeferrability &&
12095
- (currcon->condeferrable != cmdcon->deferrable ||
12096
- currcon->condeferred != cmdcon->initdeferred))
12137
+ if (currcon->condeferrable != cmdcon->deferrable ||
12138
+ currcon->condeferred != cmdcon->initdeferred)
12097
12139
{
12098
12140
AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple);
12099
12141
changed = true;
@@ -12113,73 +12155,87 @@ ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon,
12113
12155
*/
12114
12156
if (recurse && changed &&
12115
12157
(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
12116
- (OidIsValid(refrelid) &&
12117
- get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)))
12118
- ATExecAlterChildConstr(wqueue, cmdcon, conrel, tgrel, rel, contuple,
12119
- recurse, otherrelids, lockmode);
12158
+ get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE))
12159
+ AlterConstrDeferrabilityRecurse(wqueue, cmdcon, conrel, tgrel, rel,
12160
+ contuple, recurse, otherrelids,
12161
+ lockmode);
12162
+
12163
+ return changed;
12164
+ }
12165
+
12166
+ /*
12167
+ * Returns true if the constraint's inheritability is altered.
12168
+ */
12169
+ static bool
12170
+ ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon,
12171
+ Relation conrel, Relation rel,
12172
+ HeapTuple contuple, LOCKMODE lockmode)
12173
+ {
12174
+ Form_pg_constraint currcon;
12175
+ AttrNumber colNum;
12176
+ char *colName;
12177
+ List *children;
12178
+
12179
+ Assert(cmdcon->alterInheritability);
12180
+
12181
+ currcon = (Form_pg_constraint) GETSTRUCT(contuple);
12182
+
12183
+ /* The current implementation only works for NOT NULL constraints */
12184
+ Assert(currcon->contype == CONSTRAINT_NOTNULL);
12120
12185
12121
12186
/*
12122
- * Update the catalog for inheritability. No work if the constraint is
12123
- * already in the requested state .
12187
+ * If called to modify a constraint that's already in the desired state,
12188
+ * silently do nothing .
12124
12189
*/
12125
- if (cmdcon->alterInheritability &&
12126
- (cmdcon->noinherit != currcon->connoinherit))
12127
- {
12128
- AttrNumber colNum;
12129
- char *colName;
12130
- List *children;
12190
+ if (cmdcon->noinherit == currcon->connoinherit)
12191
+ return false;
12131
12192
12132
- /* The current implementation only works for NOT NULL constraints */
12133
- Assert(currcon->contype == CONSTRAINT_NOTNULL );
12193
+ AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple);
12194
+ CommandCounterIncrement( );
12134
12195
12135
- AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple);
12136
- CommandCounterIncrement( );
12137
- changed = true ;
12196
+ /* Fetch the column number and name */
12197
+ colNum = extractNotNullColumn(contuple );
12198
+ colName = get_attname(currcon->conrelid, colNum, false) ;
12138
12199
12139
- /* Fetch the column number and name */
12140
- colNum = extractNotNullColumn(contuple);
12141
- colName = get_attname(currcon->conrelid, colNum, false);
12200
+ /*
12201
+ * Propagate the change to children. For SET NO INHERIT, we don't
12202
+ * recursively affect children, just the immediate level.
12203
+ */
12204
+ children = find_inheritance_children(RelationGetRelid(rel),
12205
+ lockmode);
12206
+ foreach_oid(childoid, children)
12207
+ {
12208
+ ObjectAddress addr;
12142
12209
12143
- /*
12144
- * Propagate the change to children. For SET NO INHERIT, we don't
12145
- * recursively affect children, just the immediate level.
12146
- */
12147
- children = find_inheritance_children(RelationGetRelid(rel),
12148
- lockmode);
12149
- foreach_oid(childoid, children)
12210
+ if (cmdcon->noinherit)
12150
12211
{
12151
- ObjectAddress addr;
12212
+ HeapTuple childtup;
12213
+ Form_pg_constraint childcon;
12152
12214
12153
- if (cmdcon->noinherit)
12154
- {
12155
- HeapTuple childtup;
12156
- Form_pg_constraint childcon;
12157
-
12158
- childtup = findNotNullConstraint(childoid, colName);
12159
- if (!childtup)
12160
- elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation %u",
12161
- colName, childoid);
12162
- childcon = (Form_pg_constraint) GETSTRUCT(childtup);
12163
- Assert(childcon->coninhcount > 0);
12164
- childcon->coninhcount--;
12165
- childcon->conislocal = true;
12166
- CatalogTupleUpdate(conrel, &childtup->t_self, childtup);
12167
- heap_freetuple(childtup);
12168
- }
12169
- else
12170
- {
12171
- Relation childrel = table_open(childoid, NoLock);
12215
+ childtup = findNotNullConstraint(childoid, colName);
12216
+ if (!childtup)
12217
+ elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation %u",
12218
+ colName, childoid);
12219
+ childcon = (Form_pg_constraint) GETSTRUCT(childtup);
12220
+ Assert(childcon->coninhcount > 0);
12221
+ childcon->coninhcount--;
12222
+ childcon->conislocal = true;
12223
+ CatalogTupleUpdate(conrel, &childtup->t_self, childtup);
12224
+ heap_freetuple(childtup);
12225
+ }
12226
+ else
12227
+ {
12228
+ Relation childrel = table_open(childoid, NoLock);
12172
12229
12173
- addr = ATExecSetNotNull(wqueue, childrel, NameStr(currcon->conname),
12174
- colName, true, true, lockmode);
12175
- if (OidIsValid(addr.objectId))
12176
- CommandCounterIncrement();
12177
- table_close(childrel, NoLock);
12178
- }
12230
+ addr = ATExecSetNotNull(wqueue, childrel, NameStr(currcon->conname),
12231
+ colName, true, true, lockmode);
12232
+ if (OidIsValid(addr.objectId))
12233
+ CommandCounterIncrement();
12234
+ table_close(childrel, NoLock);
12179
12235
}
12180
12236
}
12181
12237
12182
- return changed ;
12238
+ return true ;
12183
12239
}
12184
12240
12185
12241
/*
@@ -12248,21 +12304,21 @@ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
12248
12304
}
12249
12305
12250
12306
/*
12251
- * Invokes ATExecAlterConstraintInternal for each constraint that is a child of
12307
+ * Invokes ATExecAlterConstrDeferrability for each constraint that is a child of
12252
12308
* the specified constraint.
12253
12309
*
12254
12310
* Note that this doesn't handle recursion the normal way, viz. by scanning the
12255
12311
* list of child relations and recursing; instead it uses the conparentid
12256
12312
* relationships. This may need to be reconsidered.
12257
12313
*
12258
12314
* The arguments to this function have the same meaning as the arguments to
12259
- * ATExecAlterConstraintInternal .
12315
+ * ATExecAlterConstrDeferrability .
12260
12316
*/
12261
12317
static void
12262
- ATExecAlterChildConstr (List **wqueue, ATAlterConstraint *cmdcon,
12263
- Relation conrel, Relation tgrel, Relation rel,
12264
- HeapTuple contuple, bool recurse, List **otherrelids ,
12265
- LOCKMODE lockmode)
12318
+ AlterConstrDeferrabilityRecurse (List **wqueue, ATAlterConstraint *cmdcon,
12319
+ Relation conrel, Relation tgrel, Relation rel,
12320
+ HeapTuple contuple, bool recurse,
12321
+ List **otherrelids, LOCKMODE lockmode)
12266
12322
{
12267
12323
Form_pg_constraint currcon;
12268
12324
Oid conoid;
@@ -12287,8 +12343,9 @@ ATExecAlterChildConstr(List **wqueue, ATAlterConstraint *cmdcon,
12287
12343
Relation childrel;
12288
12344
12289
12345
childrel = table_open(childcon->conrelid, lockmode);
12290
- ATExecAlterConstraintInternal(wqueue, cmdcon, conrel, tgrel, childrel,
12291
- childtup, recurse, otherrelids, lockmode);
12346
+
12347
+ ATExecAlterConstrDeferrability(wqueue, cmdcon, conrel, tgrel, childrel,
12348
+ childtup, recurse, otherrelids, lockmode);
12292
12349
table_close(childrel, NoLock);
12293
12350
}
12294
12351
0 commit comments