diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2020-04-09 14:10:01 +0200 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2020-05-08 09:18:15 +0200 |
commit | bf7233ee4a546219b078b5a0afc654ec02958bee (patch) | |
tree | 9e2155e7f7776ccd9669e8c4c2fc1aaf8d84d246 /src/backend/commands/tablecmds.c | |
parent | fc3461c8a2ad2b4a2965f5fa871834ad7cd141ee (diff) | |
download | postgresql-bf7233ee4a546219b078b5a0afc654ec02958bee.tar.gz postgresql-bf7233ee4a546219b078b5a0afc654ec02958bee.zip |
Propagate ALTER TABLE ... SET STORAGE to indexes
When creating a new index, the attstorage setting of the table column
is copied to regular (non-expression) index columns. But a later
ALTER TABLE ... SET STORAGE is not propagated to indexes, thus
creating an inconsistent and undumpable state.
Discussion: https://www.postgresql.org/message-id/flat/9765d72b-37c0-06f5-e349-2a580aafd989%402ndquadrant.com
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 1a6ccff8f1c..b36683e7497 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -6973,6 +6973,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc Form_pg_attribute attrtuple; AttrNumber attnum; ObjectAddress address; + ListCell *lc; Assert(IsA(newValue, String)); storagemode = strVal(newValue); @@ -7032,6 +7033,52 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc heap_freetuple(tuple); + /* + * Apply the change to indexes as well (only for simple index columns, + * matching behavior of index.c ConstructTupleDescriptor()). + */ + foreach(lc, RelationGetIndexList(rel)) + { + Oid indexoid = lfirst_oid(lc); + Relation indrel; + AttrNumber indattnum = 0; + + indrel = index_open(indexoid, lockmode); + + for (int i = 0; i < indrel->rd_index->indnatts; i++) + { + if (indrel->rd_index->indkey.values[i] == attnum) + { + indattnum = i + 1; + break; + } + } + + if (indattnum == 0) + { + index_close(indrel, lockmode); + continue; + } + + tuple = SearchSysCacheCopyAttNum(RelationGetRelid(indrel), indattnum); + + if (HeapTupleIsValid(tuple)) + { + attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); + attrtuple->attstorage = newstorage; + + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + + InvokeObjectPostAlterHook(RelationRelationId, + RelationGetRelid(rel), + attrtuple->attnum); + + heap_freetuple(tuple); + } + + index_close(indrel, lockmode); + } + table_close(attrelation, RowExclusiveLock); ObjectAddressSubSet(address, RelationRelationId, |