From 63fb0ea13e86760ab0460bf7f3dd165baf32032d Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Tue, 15 Sep 2026 07:46:39 -0400 Subject: [PATCH] Warn when a reset of toast_value_type drops oid8 from a dump toast_value_type is read only when a TOAST relation is created, so a reset leaves the TOAST relation alone: a relation created with oid8 keeps it, and pg_attribute becomes the only place recording the type in use. Nothing fails, and the chunk identifiers are assigned afresh on a restore, but the dump carries no trace of the type that was dropped and the relation comes back limited to 2^32 out-of-line values. That matters because restoring an oid8 relation holding more than four billion out-of-line values into an oid TOAST relation spins in GetNewOidWithIndex(), so the first sign of trouble can be a restore that does not finish, on exactly the relations big enough to have wanted oid8. Report the loss where it happens rather than leaving it to be found on the restore. Only a reset naming toast_value_type is reported, so resetting other options on the same relation stays quiet, as does a reset on a relation whose TOAST relation uses oid. This is deliberately the smallest change that removes the silence; it does not touch what pg_dump emits. Discussion: https://postgr.es/m/aqj6yd7ztQldv4Tu@paquier.xyz --- src/backend/commands/tablecmds.c | 30 +++++++++++++++++++++++++++ src/test/regress/expected/strings.out | 3 +++ 2 files changed, 33 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 2f073ddb84a..ba7e0931099 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17355,6 +17355,36 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, newOptions = transformRelOptions(datum, defList, NULL, validnsps, false, operation == AT_ResetRelOptions); + /* + * A reset of toast_value_type leaves the TOAST relation alone, so a + * relation created with oid8 keeps it, and pg_attribute becomes the only + * place recording the type in use. Nothing fails, but a later dump and + * restore recreates the TOAST relation from the reloptions and so hands + * the relation back limited to 2^32 out-of-line values. Say so, since + * the loss is otherwise silent and only shows up on the restore. + */ + if (operation == AT_ResetRelOptions && + RelationGetToastChunkIdType(rel) == OID8OID) + { + ListCell *cell; + + foreach(cell, defList) + { + DefElem *def = (DefElem *) lfirst(cell); + + if (def->defnamespace != NULL || + strcmp(def->defname, "toast_value_type") != 0) + continue; + + ereport(WARNING, + (errmsg("TOAST relation of \"%s\" keeps \"oid8\" as the type of its \"chunk_id\"", + RelationGetRelationName(rel)), + errdetail("The type in use is only read when the TOAST relation is created."), + errhint("Set \"toast_value_type\" to \"oid8\" to have a dump and restore preserve it."))); + break; + } + } + /* Validate */ switch (rel->rd_rel->relkind) { diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index fa29abfd829..902a3671e28 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -2304,6 +2304,9 @@ SELECT c1.relname, a.atttypid::regtype ALTER TABLE toasttest_oid RESET (toast_value_type); ALTER TABLE toasttest_oid8 RESET (toast_value_type); +WARNING: TOAST relation of "toasttest_oid8" keeps "oid8" as the type of its "chunk_id" +DETAIL: The type in use is only read when the TOAST relation is created. +HINT: Set "toast_value_type" to "oid8" to have a dump and restore preserve it. -- Reset column storage to its default ALTER TABLE toasttest_oid ALTER COLUMN f1 SET STORAGE EXTENDED; ALTER TABLE toasttest_oid8 ALTER COLUMN f1 SET STORAGE EXTENDED; -- 2.50.1 (Apple Git-155)