agora inbox for pgsql-hackers@postgresql.org  
help / color / mirror / Atom feed
[PATCH v9 4/8] Simplify autovacuum's TOAST-to-main-relation reloptions map.
835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ 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; 835+ messages in thread

From: Nathan Bossart @ 2026-08-07 15:55 UTC (permalink / raw)

do_autovacuum() adds an entry to this map for every relation that
has a TOAST table, and uses a flag to mark the entries that have no
reloptions to pass down.  The unconditional entry made sense back
when the payload was the main relation's OID: commit 7d4c9a5793
added the map so that the TOAST pass could find the parent, whose
pg_autovacuum row supplied the settings for a TOAST table that had
none of its own.  Commit 834a6da4f7 replaced that lookup by copying
the parent's reloptions into the entry, which left the OID unread
and called for the flag, since a by-value AutoVacOpts cannot say
"not set".

An entry is now worth creating only when there is something to
inherit, so skip the relations that have no reloptions and let a
successful lookup speak for itself.  Two relations cannot share a
TOAST table, and each pass sees a single catalog snapshot, so an
insertion can never find an existing entry; assert that rather than
quietly ignoring it.

While at it, remove two more leftovers of that same conversion:
ar_relid, unread ever since, and a NULL test on table_toast_map in
table_recheck_autovac(), which used to carry the relkind test for
get_pg_autovacuum_tuple_relid() and has had no NULL to catch since
that function went away.
---
 src/backend/postmaster/autovacuum.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index c8a1b66ca2e..32efe967890 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -200,8 +200,6 @@ typedef struct avw_dbase
 typedef struct av_relation
 {
 	Oid			ar_toastrelid;	/* hash key - must be first */
-	Oid			ar_relid;
-	bool		ar_hasrelopts;
 	StdRdOptions ar_reloptions; /* copy of main table's reloptions */
 } av_relation;
 
@@ -2097,7 +2095,7 @@ do_autovacuum(void)
 		 * this whether or not the table is going to be vacuumed, because we
 		 * don't automatically vacuum toast tables along the parent table.
 		 */
-		if (OidIsValid(classForm->reltoastrelid))
+		if (OidIsValid(classForm->reltoastrelid) && relopts)
 		{
 			av_relation *hentry;
 			bool		found;
@@ -2105,19 +2103,10 @@ do_autovacuum(void)
 			hentry = hash_search(table_toast_map,
 								 &classForm->reltoastrelid,
 								 HASH_ENTER, &found);
+			Assert(!found);		/* rels cannot share a TOAST table */
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				hentry->ar_relid = relid;
-				hentry->ar_hasrelopts = false;
-				if (relopts != NULL)
-				{
-					hentry->ar_hasrelopts = true;
-					memcpy(&hentry->ar_reloptions, relopts,
-						   sizeof(StdRdOptions));
-				}
-			}
+			/* hash_search already filled in the key */
+			memcpy(&hentry->ar_reloptions, relopts, sizeof(StdRdOptions));
 		}
 
 		/* Release stuff to avoid per-relation leakage */
@@ -2166,7 +2155,7 @@ do_autovacuum(void)
 			bool		found;
 
 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-			if (found && hentry->ar_hasrelopts)
+			if (found)
 				relopts = &hentry->ar_reloptions;
 		}
 
@@ -2809,14 +2798,13 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	relopts = (StdRdOptions *) extractRelOptions(classTup, pg_class_desc, NULL);
 	if (relopts)
 		free_relopts = true;
-	else if (classForm->relkind == RELKIND_TOASTVALUE &&
-			 table_toast_map != NULL)
+	else if (classForm->relkind == RELKIND_TOASTVALUE)
 	{
 		av_relation *hentry;
 		bool		found;
 
 		hentry = hash_search(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] 835+ messages in thread


end of thread, other threads:[~2026-08-07 15:55 UTC | newest]

Thread overview: 835+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 v13 1/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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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