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
This commit is contained in:
parent
f918b5d219
commit
03a8a5f2d4
|
@ -305,6 +305,10 @@ ALTER TABLE toasted_several REPLICA IDENTITY FULL;
|
|||
ALTER TABLE toasted_several ALTER COLUMN toasted_key SET STORAGE EXTERNAL;
|
||||
ALTER TABLE toasted_several ALTER COLUMN toasted_col1 SET STORAGE EXTERNAL;
|
||||
ALTER TABLE toasted_several ALTER COLUMN toasted_col2 SET STORAGE EXTERNAL;
|
||||
-- Change the storage of the index back to EXTENDED, separately from
|
||||
-- the table. This is currently not doable via DDL, but it is
|
||||
-- supported internally.
|
||||
UPDATE pg_attribute SET attstorage = 'x' WHERE attrelid = 'toasted_several_pkey'::regclass AND attname = 'toasted_key';
|
||||
INSERT INTO toasted_several(toasted_key) VALUES(repeat('9876543210', 10000));
|
||||
SELECT pg_column_size(toasted_key) > 2^16 FROM toasted_several;
|
||||
?column?
|
||||
|
|
|
@ -279,6 +279,11 @@ ALTER TABLE toasted_several ALTER COLUMN toasted_key SET STORAGE EXTERNAL;
|
|||
ALTER TABLE toasted_several ALTER COLUMN toasted_col1 SET STORAGE EXTERNAL;
|
||||
ALTER TABLE toasted_several ALTER COLUMN toasted_col2 SET STORAGE EXTERNAL;
|
||||
|
||||
-- Change the storage of the index back to EXTENDED, separately from
|
||||
-- the table. This is currently not doable via DDL, but it is
|
||||
-- supported internally.
|
||||
UPDATE pg_attribute SET attstorage = 'x' WHERE attrelid = 'toasted_several_pkey'::regclass AND attname = 'toasted_key';
|
||||
|
||||
INSERT INTO toasted_several(toasted_key) VALUES(repeat('9876543210', 10000));
|
||||
SELECT pg_column_size(toasted_key) > 2^16 FROM toasted_several;
|
||||
|
||||
|
|
|
@ -6734,6 +6734,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);
|
||||
|
@ -6793,6 +6794,53 @@ 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;
|
||||
int i;
|
||||
AttrNumber indattnum = 0;
|
||||
|
||||
indrel = index_open(indexoid, lockmode);
|
||||
|
||||
for (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);
|
||||
}
|
||||
|
||||
heap_close(attrelation, RowExclusiveLock);
|
||||
|
||||
ObjectAddressSubSet(address, RelationRelationId,
|
||||
|
|
|
@ -2255,6 +2255,26 @@ where oid = 'test_storage'::regclass;
|
|||
t
|
||||
(1 row)
|
||||
|
||||
-- test that SET STORAGE propagates to index correctly
|
||||
create index test_storage_idx on test_storage (b, a);
|
||||
alter table test_storage alter column a set storage external;
|
||||
\d+ test_storage
|
||||
Table "public.test_storage"
|
||||
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
|
||||
--------+---------+-----------+----------+---------+----------+--------------+-------------
|
||||
a | text | | | | external | |
|
||||
b | integer | | | 0 | plain | |
|
||||
Indexes:
|
||||
"test_storage_idx" btree (b, a)
|
||||
|
||||
\d+ test_storage_idx
|
||||
Index "public.test_storage_idx"
|
||||
Column | Type | Key? | Definition | Storage | Stats target
|
||||
--------+---------+------+------------+----------+--------------
|
||||
b | integer | yes | b | plain |
|
||||
a | text | yes | a | external |
|
||||
btree, for table "public.test_storage"
|
||||
|
||||
-- ALTER COLUMN TYPE with a check constraint and a child table (bug #13779)
|
||||
CREATE TABLE test_inh_check (a float check (a > 10.2), b float);
|
||||
CREATE TABLE test_inh_check_child() INHERITS(test_inh_check);
|
||||
|
|
|
@ -1503,6 +1503,12 @@ select reltoastrelid <> 0 as has_toast_table
|
|||
from pg_class
|
||||
where oid = 'test_storage'::regclass;
|
||||
|
||||
-- test that SET STORAGE propagates to index correctly
|
||||
create index test_storage_idx on test_storage (b, a);
|
||||
alter table test_storage alter column a set storage external;
|
||||
\d+ test_storage
|
||||
\d+ test_storage_idx
|
||||
|
||||
-- ALTER COLUMN TYPE with a check constraint and a child table (bug #13779)
|
||||
CREATE TABLE test_inh_check (a float check (a > 10.2), b float);
|
||||
CREATE TABLE test_inh_check_child() INHERITS(test_inh_check);
|
||||
|
|
Loading…
Reference in New Issue