@@ -372,6 +372,9 @@ static void ATPrepAlterColumnType(List **wqueue,
372
372
static bool ATColumnChangeRequiresRewrite (Node * expr , AttrNumber varattno );
373
373
static void ATExecAlterColumnType (AlteredTableInfo * tab , Relation rel ,
374
374
AlterTableCmd * cmd , LOCKMODE lockmode );
375
+ static void RememberConstraintForRebuilding (Oid conoid , AlteredTableInfo * tab ,
376
+ DependencyType deptype );
377
+ static void RememberIndexForRebuilding (Oid indoid , AlteredTableInfo * tab );
375
378
static void ATExecAlterColumnGenericOptions (Relation rel , const char * colName ,
376
379
List * options , LOCKMODE lockmode );
377
380
static void ATPostAlterTypeCleanup (List * * wqueue , AlteredTableInfo * tab , LOCKMODE lockmode );
@@ -7787,9 +7790,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
7787
7790
ScanKeyData key [3 ];
7788
7791
SysScanDesc scan ;
7789
7792
HeapTuple depTup ;
7790
- ListCell * lc ;
7791
- ListCell * prev ;
7792
- ListCell * next ;
7793
7793
7794
7794
attrelation = heap_open (AttributeRelationId , RowExclusiveLock );
7795
7795
@@ -7858,11 +7858,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
7858
7858
* performed all the individual ALTER TYPE operations. We have to save
7859
7859
* the info before executing ALTER TYPE, though, else the deparser will
7860
7860
* get confused.
7861
- *
7862
- * There could be multiple entries for the same object, so we must check
7863
- * to ensure we process each one only once. Note: we assume that an index
7864
- * that implements a constraint will not show a direct dependency on the
7865
- * column.
7866
7861
*/
7867
7862
depRel = heap_open (DependRelationId , RowExclusiveLock );
7868
7863
@@ -7903,20 +7898,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
7903
7898
7904
7899
if (relKind == RELKIND_INDEX )
7905
7900
{
7906
- /*
7907
- * Indexes that are directly dependent on the table
7908
- * might be regular indexes or constraint indexes.
7909
- * Constraint indexes typically have only indirect
7910
- * dependencies; but there are exceptions, notably
7911
- * partial exclusion constraints. Hence we must check
7912
- * whether the index depends on any constraint that's
7913
- * due to be rebuilt, which we'll do below after we've
7914
- * found all such constraints.
7915
- */
7916
7901
Assert (foundObject .objectSubId == 0 );
7917
- tab -> changedIndexOids =
7918
- list_append_unique_oid (tab -> changedIndexOids ,
7919
- foundObject .objectId );
7902
+ RememberIndexForRebuilding (foundObject .objectId , tab );
7920
7903
}
7921
7904
else if (relKind == RELKIND_SEQUENCE )
7922
7905
{
@@ -7937,39 +7920,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
7937
7920
7938
7921
case OCLASS_CONSTRAINT :
7939
7922
Assert (foundObject .objectSubId == 0 );
7940
- if (!list_member_oid (tab -> changedConstraintOids ,
7941
- foundObject .objectId ))
7942
- {
7943
- char * defstring = pg_get_constraintdef_string (foundObject .objectId );
7944
-
7945
- /*
7946
- * Put NORMAL dependencies at the front of the list and
7947
- * AUTO dependencies at the back. This makes sure that
7948
- * foreign-key constraints depending on this column will
7949
- * be dropped before unique or primary-key constraints of
7950
- * the column; which we must have because the FK
7951
- * constraints depend on the indexes belonging to the
7952
- * unique constraints.
7953
- */
7954
- if (foundDep -> deptype == DEPENDENCY_NORMAL )
7955
- {
7956
- tab -> changedConstraintOids =
7957
- lcons_oid (foundObject .objectId ,
7958
- tab -> changedConstraintOids );
7959
- tab -> changedConstraintDefs =
7960
- lcons (defstring ,
7961
- tab -> changedConstraintDefs );
7962
- }
7963
- else
7964
- {
7965
- tab -> changedConstraintOids =
7966
- lappend_oid (tab -> changedConstraintOids ,
7967
- foundObject .objectId );
7968
- tab -> changedConstraintDefs =
7969
- lappend (tab -> changedConstraintDefs ,
7970
- defstring );
7971
- }
7972
- }
7923
+ RememberConstraintForRebuilding (foundObject .objectId , tab ,
7924
+ foundDep -> deptype );
7973
7925
break ;
7974
7926
7975
7927
case OCLASS_REWRITE :
@@ -8052,41 +8004,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
8052
8004
8053
8005
systable_endscan (scan );
8054
8006
8055
- /*
8056
- * Check the collected index OIDs to see which ones belong to the
8057
- * constraint(s) of the table, and drop those from the list of indexes
8058
- * that we need to process; rebuilding the constraints will handle them.
8059
- */
8060
- prev = NULL ;
8061
- for (lc = list_head (tab -> changedIndexOids ); lc ; lc = next )
8062
- {
8063
- Oid indexoid = lfirst_oid (lc );
8064
- Oid conoid ;
8065
-
8066
- next = lnext (lc );
8067
-
8068
- conoid = get_index_constraint (indexoid );
8069
- if (OidIsValid (conoid ) &&
8070
- list_member_oid (tab -> changedConstraintOids , conoid ))
8071
- tab -> changedIndexOids = list_delete_cell (tab -> changedIndexOids ,
8072
- lc , prev );
8073
- else
8074
- prev = lc ;
8075
- }
8076
-
8077
- /*
8078
- * Now collect the definitions of the indexes that must be rebuilt. (We
8079
- * could merge this into the previous loop, but it'd be more complicated
8080
- * for little gain.)
8081
- */
8082
- foreach (lc , tab -> changedIndexOids )
8083
- {
8084
- Oid indexoid = lfirst_oid (lc );
8085
-
8086
- tab -> changedIndexDefs = lappend (tab -> changedIndexDefs ,
8087
- pg_get_indexdef_string (indexoid ));
8088
- }
8089
-
8090
8007
/*
8091
8008
* Now scan for dependencies of this column on other things. The only
8092
8009
* thing we should find is the dependency on the column datatype, which we
@@ -8188,6 +8105,95 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
8188
8105
heap_freetuple (heapTup );
8189
8106
}
8190
8107
8108
+ /*
8109
+ * Subroutine for ATExecAlterColumnType: remember that a constraint needs
8110
+ * to be rebuilt (which we might already know).
8111
+ */
8112
+ static void
8113
+ RememberConstraintForRebuilding (Oid conoid , AlteredTableInfo * tab ,
8114
+ DependencyType deptype )
8115
+ {
8116
+ /*
8117
+ * This de-duplication check is critical for two independent reasons: we
8118
+ * mustn't try to recreate the same constraint twice, and if a constraint
8119
+ * depends on more than one column whose type is to be altered, we must
8120
+ * capture its definition string before applying any of the column type
8121
+ * changes. ruleutils.c will get confused if we ask again later.
8122
+ */
8123
+ if (!list_member_oid (tab -> changedConstraintOids , conoid ))
8124
+ {
8125
+ /* OK, capture the constraint's existing definition string */
8126
+ char * defstring = pg_get_constraintdef_string (conoid );
8127
+
8128
+ /*
8129
+ * Put NORMAL dependencies at the front of the list and AUTO
8130
+ * dependencies at the back. This makes sure that foreign-key
8131
+ * constraints depending on this column will be dropped before unique
8132
+ * or primary-key constraints of the column; which we must have
8133
+ * because the FK constraints depend on the indexes belonging to the
8134
+ * unique constraints.
8135
+ */
8136
+ if (deptype == DEPENDENCY_NORMAL )
8137
+ {
8138
+ tab -> changedConstraintOids = lcons_oid (conoid ,
8139
+ tab -> changedConstraintOids );
8140
+ tab -> changedConstraintDefs = lcons (defstring ,
8141
+ tab -> changedConstraintDefs );
8142
+ }
8143
+ else
8144
+ {
8145
+ tab -> changedConstraintOids = lappend_oid (tab -> changedConstraintOids ,
8146
+ conoid );
8147
+ tab -> changedConstraintDefs = lappend (tab -> changedConstraintDefs ,
8148
+ defstring );
8149
+ }
8150
+ }
8151
+ }
8152
+
8153
+ /*
8154
+ * Subroutine for ATExecAlterColumnType: remember that an index needs
8155
+ * to be rebuilt (which we might already know).
8156
+ */
8157
+ static void
8158
+ RememberIndexForRebuilding (Oid indoid , AlteredTableInfo * tab )
8159
+ {
8160
+ /*
8161
+ * This de-duplication check is critical for two independent reasons: we
8162
+ * mustn't try to recreate the same index twice, and if an index depends
8163
+ * on more than one column whose type is to be altered, we must capture
8164
+ * its definition string before applying any of the column type changes.
8165
+ * ruleutils.c will get confused if we ask again later.
8166
+ */
8167
+ if (!list_member_oid (tab -> changedIndexOids , indoid ))
8168
+ {
8169
+ /*
8170
+ * Before adding it as an index-to-rebuild, we'd better see if it
8171
+ * belongs to a constraint, and if so rebuild the constraint instead.
8172
+ * Typically this check fails, because constraint indexes normally
8173
+ * have only dependencies on their constraint. But it's possible for
8174
+ * such an index to also have direct dependencies on table columns,
8175
+ * for example with a partial exclusion constraint.
8176
+ */
8177
+ Oid conoid = get_index_constraint (indoid );
8178
+
8179
+ if (OidIsValid (conoid ))
8180
+ {
8181
+ /* index dependencies on columns should generally be AUTO */
8182
+ RememberConstraintForRebuilding (conoid , tab , DEPENDENCY_AUTO );
8183
+ }
8184
+ else
8185
+ {
8186
+ /* OK, capture the index's existing definition string */
8187
+ char * defstring = pg_get_indexdef_string (indoid );
8188
+
8189
+ tab -> changedIndexOids = lappend_oid (tab -> changedIndexOids ,
8190
+ indoid );
8191
+ tab -> changedIndexDefs = lappend (tab -> changedIndexDefs ,
8192
+ defstring );
8193
+ }
8194
+ }
8195
+ }
8196
+
8191
8197
static void
8192
8198
ATExecAlterColumnGenericOptions (Relation rel ,
8193
8199
const char * colName ,
0 commit comments