agora inbox for pgsql-hackers@postgresql.orghelp / color / mirror / Atom feed
[PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. 919+ messages / 1 participants [nested] [flat]
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --WiF/3tUCR6j/q9wa Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v10-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --jWUVADOU6pvU/6ap Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v7-0005-Fix-VACUUM-and-autovacuum-handling-of-TOAST-stora.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --IZet2WR372zTYuyO Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v11-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --QnbX+ZG8KQOMO1rs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v8-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.50.1 (Apple Git-155) --0oaK7sfrjhxPo9Xw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v9-0005-Give-TOAST-storage-parameters-unsettable-defaults.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c8a1b66ca2e..32efe967890 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2097,7 +2095,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2105,19 +2103,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2166,7 +2155,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --gzHy1cBrLyG9oicL Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v12-0005-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
* [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. @ 2026-08-07 15:55 Nathan Bossart <nathan@postgresql.org> 0 siblings, 0 replies; 919+ messages in thread From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw) do_autovacuum() adds an entry to this map for every relation that has a TOAST table, and uses a flag to mark the entries that have no reloptions to pass down. The unconditional entry made sense back when the payload was the main relation's OID: commit 7d4c9a5793 added the map so that the TOAST pass could find the parent, whose pg_autovacuum row supplied the settings for a TOAST table that had none of its own. Commit 834a6da4f7 replaced that lookup by copying the parent's reloptions into the entry, which left the OID unread and called for the flag, since a by-value AutoVacOpts cannot say "not set". An entry is now worth creating only when there is something to inherit, so skip the relations that have no reloptions and let a successful lookup speak for itself. Two relations cannot share a TOAST table, and each pass sees a single catalog snapshot, so an insertion can never find an existing entry; assert that rather than quietly ignoring it. While at it, remove two more leftovers of that same conversion: ar_relid, unread ever since, and a NULL test on table_toast_map in table_recheck_autovac(), which used to carry the relkind test for get_pg_autovacuum_tuple_relid() and has had no NULL to catch since that function went away. --- src/backend/postmaster/autovacuum.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 874454891d3..e0fc551d12a 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -200,8 +200,6 @@ typedef struct avw_dbase typedef struct av_relation { Oid ar_toastrelid; /* hash key - must be first */ - Oid ar_relid; - bool ar_hasrelopts; StdRdOptions ar_reloptions; /* copy of main table's reloptions */ } av_relation; @@ -2099,7 +2097,7 @@ do_autovacuum(void) * this whether or not the table is going to be vacuumed, because we * don't automatically vacuum toast tables along the parent table. */ - if (OidIsValid(classForm->reltoastrelid)) + if (OidIsValid(classForm->reltoastrelid) && relopts) { av_relation *hentry; bool found; @@ -2107,19 +2105,10 @@ do_autovacuum(void) hentry = hash_search(table_toast_map, &classForm->reltoastrelid, HASH_ENTER, &found); + Assert(!found); /* rels cannot share a TOAST table */ - if (!found) - { - /* hash_search already filled in the key */ - hentry->ar_relid = relid; - hentry->ar_hasrelopts = false; - if (relopts != NULL) - { - hentry->ar_hasrelopts = true; - memcpy(&hentry->ar_reloptions, relopts, - sizeof(StdRdOptions)); - } - } + /* hash_search already filled in the key */ + memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions)); } /* Release stuff to avoid per-relation leakage */ @@ -2168,7 +2157,7 @@ do_autovacuum(void) bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } @@ -2814,14 +2803,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL); if (relopts) free_relopts = true; - else if (classForm->relkind == RELKIND_TOASTVALUE && - table_toast_map != NULL) + else if (classForm->relkind == RELKIND_TOASTVALUE) { av_relation *hentry; bool found; hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) + if (found) relopts = &hentry->ar_reloptions; } -- 2.55.0 --WFulFp79iVB4kETe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v13-0002-Give-TOAST-storage-parameters-unsettable-default.patch ^ permalink raw reply [nested|flat] 919+ messages in thread
end of thread, other threads:[~2026-08-07 15:55 UTC | newest] Thread overview: 919+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v12 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v13 1/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v10 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v8 4/7] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v7 4/5] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v11 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org> 2026-08-07 15:55 [PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map. Nathan Bossart <nathan@postgresql.org>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox