@@ -415,6 +415,9 @@ static void ATPrepAlterColumnType(List **wqueue,
415
415
static bool ATColumnChangeRequiresRewrite (Node * expr , AttrNumber varattno );
416
416
static ObjectAddress ATExecAlterColumnType (AlteredTableInfo * tab , Relation rel ,
417
417
AlterTableCmd * cmd , LOCKMODE lockmode );
418
+ static void RememberConstraintForRebuilding (Oid conoid , AlteredTableInfo * tab ,
419
+ DependencyType deptype );
420
+ static void RememberIndexForRebuilding (Oid indoid , AlteredTableInfo * tab );
418
421
static ObjectAddress ATExecAlterColumnGenericOptions (Relation rel , const char * colName ,
419
422
List * options , LOCKMODE lockmode );
420
423
static void ATPostAlterTypeCleanup (List * * wqueue , AlteredTableInfo * tab ,
@@ -9021,9 +9024,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
9021
9024
SysScanDesc scan ;
9022
9025
HeapTuple depTup ;
9023
9026
ObjectAddress address ;
9024
- ListCell * lc ;
9025
- ListCell * prev ;
9026
- ListCell * next ;
9027
9027
9028
9028
attrelation = heap_open (AttributeRelationId , RowExclusiveLock );
9029
9029
@@ -9092,11 +9092,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
9092
9092
* performed all the individual ALTER TYPE operations. We have to save
9093
9093
* the info before executing ALTER TYPE, though, else the deparser will
9094
9094
* get confused.
9095
- *
9096
- * There could be multiple entries for the same object, so we must check
9097
- * to ensure we process each one only once. Note: we assume that an index
9098
- * that implements a constraint will not show a direct dependency on the
9099
- * column.
9100
9095
*/
9101
9096
depRel = heap_open (DependRelationId , RowExclusiveLock );
9102
9097
@@ -9137,20 +9132,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
9137
9132
9138
9133
if (relKind == RELKIND_INDEX )
9139
9134
{
9140
- /*
9141
- * Indexes that are directly dependent on the table
9142
- * might be regular indexes or constraint indexes.
9143
- * Constraint indexes typically have only indirect
9144
- * dependencies; but there are exceptions, notably
9145
- * partial exclusion constraints. Hence we must check
9146
- * whether the index depends on any constraint that's
9147
- * due to be rebuilt, which we'll do below after we've
9148
- * found all such constraints.
9149
- */
9150
9135
Assert (foundObject .objectSubId == 0 );
9151
- tab -> changedIndexOids =
9152
- list_append_unique_oid (tab -> changedIndexOids ,
9153
- foundObject .objectId );
9136
+ RememberIndexForRebuilding (foundObject .objectId , tab );
9154
9137
}
9155
9138
else if (relKind == RELKIND_SEQUENCE )
9156
9139
{
@@ -9171,39 +9154,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
9171
9154
9172
9155
case OCLASS_CONSTRAINT :
9173
9156
Assert (foundObject .objectSubId == 0 );
9174
- if (!list_member_oid (tab -> changedConstraintOids ,
9175
- foundObject .objectId ))
9176
- {
9177
- char * defstring = pg_get_constraintdef_command (foundObject .objectId );
9178
-
9179
- /*
9180
- * Put NORMAL dependencies at the front of the list and
9181
- * AUTO dependencies at the back. This makes sure that
9182
- * foreign-key constraints depending on this column will
9183
- * be dropped before unique or primary-key constraints of
9184
- * the column; which we must have because the FK
9185
- * constraints depend on the indexes belonging to the
9186
- * unique constraints.
9187
- */
9188
- if (foundDep -> deptype == DEPENDENCY_NORMAL )
9189
- {
9190
- tab -> changedConstraintOids =
9191
- lcons_oid (foundObject .objectId ,
9192
- tab -> changedConstraintOids );
9193
- tab -> changedConstraintDefs =
9194
- lcons (defstring ,
9195
- tab -> changedConstraintDefs );
9196
- }
9197
- else
9198
- {
9199
- tab -> changedConstraintOids =
9200
- lappend_oid (tab -> changedConstraintOids ,
9201
- foundObject .objectId );
9202
- tab -> changedConstraintDefs =
9203
- lappend (tab -> changedConstraintDefs ,
9204
- defstring );
9205
- }
9206
- }
9157
+ RememberConstraintForRebuilding (foundObject .objectId , tab ,
9158
+ foundDep -> deptype );
9207
9159
break ;
9208
9160
9209
9161
case OCLASS_REWRITE :
@@ -9322,41 +9274,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
9322
9274
9323
9275
systable_endscan (scan );
9324
9276
9325
- /*
9326
- * Check the collected index OIDs to see which ones belong to the
9327
- * constraint(s) of the table, and drop those from the list of indexes
9328
- * that we need to process; rebuilding the constraints will handle them.
9329
- */
9330
- prev = NULL ;
9331
- for (lc = list_head (tab -> changedIndexOids ); lc ; lc = next )
9332
- {
9333
- Oid indexoid = lfirst_oid (lc );
9334
- Oid conoid ;
9335
-
9336
- next = lnext (lc );
9337
-
9338
- conoid = get_index_constraint (indexoid );
9339
- if (OidIsValid (conoid ) &&
9340
- list_member_oid (tab -> changedConstraintOids , conoid ))
9341
- tab -> changedIndexOids = list_delete_cell (tab -> changedIndexOids ,
9342
- lc , prev );
9343
- else
9344
- prev = lc ;
9345
- }
9346
-
9347
- /*
9348
- * Now collect the definitions of the indexes that must be rebuilt. (We
9349
- * could merge this into the previous loop, but it'd be more complicated
9350
- * for little gain.)
9351
- */
9352
- foreach (lc , tab -> changedIndexOids )
9353
- {
9354
- Oid indexoid = lfirst_oid (lc );
9355
-
9356
- tab -> changedIndexDefs = lappend (tab -> changedIndexDefs ,
9357
- pg_get_indexdef_string (indexoid ));
9358
- }
9359
-
9360
9277
/*
9361
9278
* Now scan for dependencies of this column on other things. The only
9362
9279
* thing we should find is the dependency on the column datatype, which we
@@ -9460,6 +9377,95 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
9460
9377
return address ;
9461
9378
}
9462
9379
9380
+ /*
9381
+ * Subroutine for ATExecAlterColumnType: remember that a constraint needs
9382
+ * to be rebuilt (which we might already know).
9383
+ */
9384
+ static void
9385
+ RememberConstraintForRebuilding (Oid conoid , AlteredTableInfo * tab ,
9386
+ DependencyType deptype )
9387
+ {
9388
+ /*
9389
+ * This de-duplication check is critical for two independent reasons: we
9390
+ * mustn't try to recreate the same constraint twice, and if a constraint
9391
+ * depends on more than one column whose type is to be altered, we must
9392
+ * capture its definition string before applying any of the column type
9393
+ * changes. ruleutils.c will get confused if we ask again later.
9394
+ */
9395
+ if (!list_member_oid (tab -> changedConstraintOids , conoid ))
9396
+ {
9397
+ /* OK, capture the constraint's existing definition string */
9398
+ char * defstring = pg_get_constraintdef_command (conoid );
9399
+
9400
+ /*
9401
+ * Put NORMAL dependencies at the front of the list and AUTO
9402
+ * dependencies at the back. This makes sure that foreign-key
9403
+ * constraints depending on this column will be dropped before unique
9404
+ * or primary-key constraints of the column; which we must have
9405
+ * because the FK constraints depend on the indexes belonging to the
9406
+ * unique constraints.
9407
+ */
9408
+ if (deptype == DEPENDENCY_NORMAL )
9409
+ {
9410
+ tab -> changedConstraintOids = lcons_oid (conoid ,
9411
+ tab -> changedConstraintOids );
9412
+ tab -> changedConstraintDefs = lcons (defstring ,
9413
+ tab -> changedConstraintDefs );
9414
+ }
9415
+ else
9416
+ {
9417
+ tab -> changedConstraintOids = lappend_oid (tab -> changedConstraintOids ,
9418
+ conoid );
9419
+ tab -> changedConstraintDefs = lappend (tab -> changedConstraintDefs ,
9420
+ defstring );
9421
+ }
9422
+ }
9423
+ }
9424
+
9425
+ /*
9426
+ * Subroutine for ATExecAlterColumnType: remember that an index needs
9427
+ * to be rebuilt (which we might already know).
9428
+ */
9429
+ static void
9430
+ RememberIndexForRebuilding (Oid indoid , AlteredTableInfo * tab )
9431
+ {
9432
+ /*
9433
+ * This de-duplication check is critical for two independent reasons: we
9434
+ * mustn't try to recreate the same index twice, and if an index depends
9435
+ * on more than one column whose type is to be altered, we must capture
9436
+ * its definition string before applying any of the column type changes.
9437
+ * ruleutils.c will get confused if we ask again later.
9438
+ */
9439
+ if (!list_member_oid (tab -> changedIndexOids , indoid ))
9440
+ {
9441
+ /*
9442
+ * Before adding it as an index-to-rebuild, we'd better see if it
9443
+ * belongs to a constraint, and if so rebuild the constraint instead.
9444
+ * Typically this check fails, because constraint indexes normally
9445
+ * have only dependencies on their constraint. But it's possible for
9446
+ * such an index to also have direct dependencies on table columns,
9447
+ * for example with a partial exclusion constraint.
9448
+ */
9449
+ Oid conoid = get_index_constraint (indoid );
9450
+
9451
+ if (OidIsValid (conoid ))
9452
+ {
9453
+ /* index dependencies on columns should generally be AUTO */
9454
+ RememberConstraintForRebuilding (conoid , tab , DEPENDENCY_AUTO );
9455
+ }
9456
+ else
9457
+ {
9458
+ /* OK, capture the index's existing definition string */
9459
+ char * defstring = pg_get_indexdef_string (indoid );
9460
+
9461
+ tab -> changedIndexOids = lappend_oid (tab -> changedIndexOids ,
9462
+ indoid );
9463
+ tab -> changedIndexDefs = lappend (tab -> changedIndexDefs ,
9464
+ defstring );
9465
+ }
9466
+ }
9467
+ }
9468
+
9463
9469
/*
9464
9470
* Returns the address of the modified column
9465
9471
*/
0 commit comments